From 693871c98f1ae0b1a6623276f93338a05e371c4a Mon Sep 17 00:00:00 2001 From: shanweiqian Date: Mon, 7 Apr 2025 21:17:09 +0800 Subject: [PATCH 1/3] optimize and adapt the program to feature branch Issue:https://gitee.com/openharmony/third_party_typescript/issues/IBZ6ZK Signed-off-by: shanweiqian Change-Id: I8946223c3cb5624e654442b5858fcca72693fef9 --- lib/tsserver.js | 4 ++++ lib/tsserverlibrary.d.ts | 1 + lib/tsserverlibrary.js | 4 ++++ lib/typescript.d.ts | 1 + lib/typescript.js | 4 ++++ lib/typescriptServices.d.ts | 1 + lib/typescriptServices.js | 4 ++++ src/services/services.ts | 4 ++++ src/services/types.ts | 1 + tests/baselines/reference/api/tsserverlibrary.d.ts | 1 + tests/baselines/reference/api/typescript.d.ts | 1 + 11 files changed, 26 insertions(+) diff --git a/lib/tsserver.js b/lib/tsserver.js index b1f67ca85b..f27cd4e88d 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -173834,6 +173834,9 @@ var ts; ts.PerformanceDotting.start("isProgramUptoDate"); if (ts.isProgramUptoDate(program, rootFileNames, newSettings, function (_path, fileName) { return host.getScriptVersion(fileName); }, function (fileName) { return compilerHost.fileExists(fileName); }, hasInvalidatedResolutions, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { ts.PerformanceDotting.stop("isProgramUptoDate"); + // During incremental compilation, executing isProgramUptoDate to check for program updates generates file caches; + // clear these caches to avoid affecting future compilations. + host.clearFileCache && host.clearFileCache(); return; } ts.PerformanceDotting.stop("isProgramUptoDate"); @@ -173877,6 +173880,7 @@ var ts; // Make sure all the nodes in the program are both bound, and have their parent // pointers set property. program.getTypeChecker(); + host.clearFileCache && host.clearFileCache(); return; function getParsedCommandLine(fileName) { var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); diff --git a/lib/tsserverlibrary.d.ts b/lib/tsserverlibrary.d.ts index 765702bc62..e492286d6d 100644 --- a/lib/tsserverlibrary.d.ts +++ b/lib/tsserverlibrary.d.ts @@ -6378,6 +6378,7 @@ declare namespace ts { shouldCompletionSortCustom?: boolean; uiProps?: string[]; clearProps?(): void; + clearFileCache?(): void; } type WithMetadata = T & { metadata?: unknown; diff --git a/lib/tsserverlibrary.js b/lib/tsserverlibrary.js index 99f576ac0f..257543d839 100644 --- a/lib/tsserverlibrary.js +++ b/lib/tsserverlibrary.js @@ -174253,6 +174253,9 @@ var ts; ts.PerformanceDotting.start("isProgramUptoDate"); if (ts.isProgramUptoDate(program, rootFileNames, newSettings, function (_path, fileName) { return host.getScriptVersion(fileName); }, function (fileName) { return compilerHost.fileExists(fileName); }, hasInvalidatedResolutions, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { ts.PerformanceDotting.stop("isProgramUptoDate"); + // During incremental compilation, executing isProgramUptoDate to check for program updates generates file caches; + // clear these caches to avoid affecting future compilations. + host.clearFileCache && host.clearFileCache(); return; } ts.PerformanceDotting.stop("isProgramUptoDate"); @@ -174296,6 +174299,7 @@ var ts; // Make sure all the nodes in the program are both bound, and have their parent // pointers set property. program.getTypeChecker(); + host.clearFileCache && host.clearFileCache(); return; function getParsedCommandLine(fileName) { var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); diff --git a/lib/typescript.d.ts b/lib/typescript.d.ts index 174833fb51..7d6cfa89e4 100644 --- a/lib/typescript.d.ts +++ b/lib/typescript.d.ts @@ -6378,6 +6378,7 @@ declare namespace ts { shouldCompletionSortCustom?: boolean; uiProps?: string[]; clearProps?(): void; + clearFileCache?(): void; } type WithMetadata = T & { metadata?: unknown; diff --git a/lib/typescript.js b/lib/typescript.js index 5630daaf70..0230549835 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -174244,6 +174244,9 @@ var ts; ts.PerformanceDotting.start("isProgramUptoDate"); if (ts.isProgramUptoDate(program, rootFileNames, newSettings, function (_path, fileName) { return host.getScriptVersion(fileName); }, function (fileName) { return compilerHost.fileExists(fileName); }, hasInvalidatedResolutions, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { ts.PerformanceDotting.stop("isProgramUptoDate"); + // During incremental compilation, executing isProgramUptoDate to check for program updates generates file caches; + // clear these caches to avoid affecting future compilations. + host.clearFileCache && host.clearFileCache(); return; } ts.PerformanceDotting.stop("isProgramUptoDate"); @@ -174287,6 +174290,7 @@ var ts; // Make sure all the nodes in the program are both bound, and have their parent // pointers set property. program.getTypeChecker(); + host.clearFileCache && host.clearFileCache(); return; function getParsedCommandLine(fileName) { var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); diff --git a/lib/typescriptServices.d.ts b/lib/typescriptServices.d.ts index 91e0b72abd..a69ea55548 100644 --- a/lib/typescriptServices.d.ts +++ b/lib/typescriptServices.d.ts @@ -6378,6 +6378,7 @@ declare namespace ts { shouldCompletionSortCustom?: boolean; uiProps?: string[]; clearProps?(): void; + clearFileCache?(): void; } type WithMetadata = T & { metadata?: unknown; diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js index 9bc8f8f7b1..16c68c26e2 100644 --- a/lib/typescriptServices.js +++ b/lib/typescriptServices.js @@ -174244,6 +174244,9 @@ var ts; ts.PerformanceDotting.start("isProgramUptoDate"); if (ts.isProgramUptoDate(program, rootFileNames, newSettings, function (_path, fileName) { return host.getScriptVersion(fileName); }, function (fileName) { return compilerHost.fileExists(fileName); }, hasInvalidatedResolutions, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { ts.PerformanceDotting.stop("isProgramUptoDate"); + // During incremental compilation, executing isProgramUptoDate to check for program updates generates file caches; + // clear these caches to avoid affecting future compilations. + host.clearFileCache && host.clearFileCache(); return; } ts.PerformanceDotting.stop("isProgramUptoDate"); @@ -174287,6 +174290,7 @@ var ts; // Make sure all the nodes in the program are both bound, and have their parent // pointers set property. program.getTypeChecker(); + host.clearFileCache && host.clearFileCache(); return; function getParsedCommandLine(fileName) { var path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); diff --git a/src/services/services.ts b/src/services/services.ts index b76fc55cce..b85f64b764 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1392,6 +1392,9 @@ namespace ts { PerformanceDotting.start("isProgramUptoDate"); if (isProgramUptoDate(program, rootFileNames, newSettings, (_path, fileName) => host.getScriptVersion(fileName), fileName => compilerHost!.fileExists(fileName), hasInvalidatedResolutions, hasChangedAutomaticTypeDirectiveNames, getParsedCommandLine, projectReferences)) { PerformanceDotting.stop("isProgramUptoDate"); + // During incremental compilation, executing isProgramUptoDate to check for program updates generates file caches; + // clear these caches to avoid affecting future compilations. + host.clearFileCache && host.clearFileCache(); return; } PerformanceDotting.stop("isProgramUptoDate"); @@ -1441,6 +1444,7 @@ namespace ts { // Make sure all the nodes in the program are both bound, and have their parent // pointers set property. program.getTypeChecker(); + host.clearFileCache && host.clearFileCache(); return; function getParsedCommandLine(fileName: string): ParsedCommandLine | undefined { diff --git a/src/services/types.ts b/src/services/types.ts index 86c25b1b82..963f1ba3f6 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -329,6 +329,7 @@ namespace ts { shouldCompletionSortCustom?: boolean; uiProps?: string[]; clearProps?(): void; + clearFileCache?(): void; } /* @internal */ diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 765702bc62..e492286d6d 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -6378,6 +6378,7 @@ declare namespace ts { shouldCompletionSortCustom?: boolean; uiProps?: string[]; clearProps?(): void; + clearFileCache?(): void; } type WithMetadata = T & { metadata?: unknown; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 174833fb51..7d6cfa89e4 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -6378,6 +6378,7 @@ declare namespace ts { shouldCompletionSortCustom?: boolean; uiProps?: string[]; clearProps?(): void; + clearFileCache?(): void; } type WithMetadata = T & { metadata?: unknown; -- Gitee From 2411ba7667cbc1bda3a39a3fbe9cb74fc99bdb53 Mon Sep 17 00:00:00 2001 From: zju_wyx Date: Mon, 17 Feb 2025 19:08:44 +0800 Subject: [PATCH 2/3] add qualifiedNameCache for linter --- lib/tsc.js | 18 ++++++++++- lib/tsserver.js | 31 ++++++++++++++++++- lib/tsserverlibrary.d.ts | 3 ++ lib/tsserverlibrary.js | 31 ++++++++++++++++++- lib/typescript.d.ts | 3 ++ lib/typescript.js | 31 ++++++++++++++++++- lib/typescriptServices.d.ts | 3 ++ lib/typescriptServices.js | 31 ++++++++++++++++++- lib/typingsInstaller.js | 19 +++++++++++- src/compiler/checker.ts | 21 ++++++++++++- src/compiler/types.ts | 1 + src/linter/ArkTSLinter_1_0/LinterRunner.ts | 1 + .../ArkTSLinter_1_0/TypeScriptLinter.ts | 6 ++++ src/linter/ArkTSLinter_1_1/LinterRunner.ts | 1 + .../ArkTSLinter_1_1/TypeScriptLinter.ts | 6 ++++ .../reference/api/tsserverlibrary.d.ts | 3 ++ tests/baselines/reference/api/typescript.d.ts | 3 ++ 17 files changed, 205 insertions(+), 7 deletions(-) diff --git a/lib/tsc.js b/lib/tsc.js index d079b6799d..b33c904480 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -42873,6 +42873,7 @@ var ts; var apparentArgumentCount; var constEnumRelate = new ts.Map(); var performanceFileName; + var qualifiedNameCache = new ts.Map(); var checker = { getNodeCount: function () { return ts.sum(host.getSourceFiles(), "nodeCount"); }, getIdentifierCount: function () { return ts.sum(host.getSourceFiles(), "identifierCount"); }, @@ -43204,6 +43205,7 @@ var ts; getConstEnumRelate: function () { return constEnumRelate; }, clearConstEnumRelate: function () { constEnumRelate && constEnumRelate.clear(); }, deleteConstEnumRelate: function (path) { constEnumRelate && constEnumRelate.delete(path); }, + clearQualifiedNameCache: function () { qualifiedNameCache && qualifiedNameCache.clear(); }, }; function runWithInferenceBlockedFromSourceNode(node, fn) { var containingCall = ts.findAncestor(node, ts.isCallLikeExpression); @@ -45371,7 +45373,21 @@ var ts; } } function getFullyQualifiedName(symbol, containingLocation) { - return symbol.parent ? getFullyQualifiedName(symbol.parent, containingLocation) + "." + symbolToString(symbol) : symbolToString(symbol, containingLocation, undefined, 32 | 4); + if (containingLocation === undefined) { + var cachedQualifiedName = qualifiedNameCache.get(symbol); + if (cachedQualifiedName) { + return cachedQualifiedName; + } + } + var qualifiedName = getFullyQualifiedNameNoCache(symbol, containingLocation); + if (isTypeCheckerForLinter && containingLocation === undefined) { + qualifiedNameCache.set(symbol, qualifiedName); + } + return qualifiedName; + } + function getFullyQualifiedNameNoCache(symbol, containingLocation) { + return symbol.parent ? getFullyQualifiedNameNoCache(symbol.parent, containingLocation) + "." + symbolToString(symbol) : + symbolToString(symbol, containingLocation, undefined, 32 | 4); } function getContainingQualifiedNameNode(node) { while (ts.isQualifiedName(node.parent)) { diff --git a/lib/tsserver.js b/lib/tsserver.js index f27cd4e88d..e67874d0a7 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -52042,6 +52042,8 @@ var ts; var apparentArgumentCount; var constEnumRelate = new ts.Map(); var performanceFileName; + // Used only for linter, in non-strict typeChecker, it is always empty. + var qualifiedNameCache = new ts.Map(); // 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 @@ -52385,6 +52387,7 @@ var ts; getConstEnumRelate: function () { return constEnumRelate; }, clearConstEnumRelate: function () { constEnumRelate && constEnumRelate.clear(); }, deleteConstEnumRelate: function (path) { constEnumRelate && constEnumRelate.delete(path); }, + clearQualifiedNameCache: function () { qualifiedNameCache && qualifiedNameCache.clear(); }, }; function runWithInferenceBlockedFromSourceNode(node, fn) { var containingCall = ts.findAncestor(node, ts.isCallLikeExpression); @@ -54895,7 +54898,21 @@ var ts; } } function getFullyQualifiedName(symbol, containingLocation) { - return symbol.parent ? getFullyQualifiedName(symbol.parent, containingLocation) + "." + symbolToString(symbol) : symbolToString(symbol, containingLocation, /*meaning*/ undefined, 32 /* SymbolFormatFlags.DoNotIncludeSymbolChain */ | 4 /* SymbolFormatFlags.AllowAnyNodeKind */); + if (containingLocation === undefined) { + var cachedQualifiedName = qualifiedNameCache.get(symbol); + if (cachedQualifiedName) { + return cachedQualifiedName; + } + } + var qualifiedName = getFullyQualifiedNameNoCache(symbol, containingLocation); + if (isTypeCheckerForLinter && containingLocation === undefined) { + qualifiedNameCache.set(symbol, qualifiedName); + } + return qualifiedName; + } + function getFullyQualifiedNameNoCache(symbol, containingLocation) { + return symbol.parent ? getFullyQualifiedNameNoCache(symbol.parent, containingLocation) + "." + symbolToString(symbol) : + symbolToString(symbol, containingLocation, /*meaning*/ undefined, 32 /* SymbolFormatFlags.DoNotIncludeSymbolChain */ | 4 /* SymbolFormatFlags.AllowAnyNodeKind */); } function getContainingQualifiedNameNode(node) { while (ts.isQualifiedName(node.parent)) { @@ -193053,6 +193070,11 @@ var ts; TypeScriptLinter.clearTsTypeChecker = function () { TypeScriptLinter.tsTypeChecker = {}; }; + TypeScriptLinter.clearQualifiedNameCache = function () { + if (TypeScriptLinter.tsTypeChecker) { + TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache && TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache(); + } + }; TypeScriptLinter.prototype.incrementCounters = function (node, faultId, autofixable, autofix) { if (autofixable === void 0) { autofixable = false; } if (!TypeScriptLinter.strictMode && faultsAttrs[faultId].migratable) { @@ -194848,6 +194870,7 @@ var ts; ArkTSLinter_1_0.runArkTSLinter = runArkTSLinter; // reclaiming memory for Hvigor with "no-parallel" and "daemon", . function releaseReferences() { + ArkTSLinter_1_0.TypeScriptLinter.clearQualifiedNameCache(); ArkTSLinter_1_0.TypeScriptLinter.clearTsTypeChecker(); ArkTSLinter_1_0.Utils.clearTypeChecker(); ArkTSLinter_1_0.Utils.clearTrueSymbolAtLocationCache(); @@ -198459,6 +198482,11 @@ var ts; TypeScriptLinter.clearTsTypeChecker = function () { TypeScriptLinter.tsTypeChecker = {}; }; + TypeScriptLinter.clearQualifiedNameCache = function () { + if (TypeScriptLinter.tsTypeChecker) { + TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache && TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache(); + } + }; TypeScriptLinter.prototype.incrementCounters = function (node, faultId, autofixable, autofix) { var _a, _b; if (autofixable === void 0) { autofixable = false; } @@ -201284,6 +201312,7 @@ var ts; ArkTSLinter_1_1.runArkTSLinter = runArkTSLinter; // reclaiming memory for Hvigor with "no-parallel" and "daemon", . function releaseReferences() { + ArkTSLinter_1_1.TypeScriptLinter.clearQualifiedNameCache(); ArkTSLinter_1_1.TypeScriptLinter.clearTsTypeChecker(); ArkTSLinter_1_1.InteropTypescriptLinter.clearTsTypeChecker(); ArkTSLinter_1_1.Utils.clearTypeChecker(); diff --git a/lib/tsserverlibrary.d.ts b/lib/tsserverlibrary.d.ts index e492286d6d..a07c00f2a5 100644 --- a/lib/tsserverlibrary.d.ts +++ b/lib/tsserverlibrary.d.ts @@ -2543,6 +2543,7 @@ declare namespace ts { getConstEnumRelate?(): ESMap>; clearConstEnumRelate?(): void; deleteConstEnumRelate?(path: string): void; + clearQualifiedNameCache?(): void; } export enum NodeBuilderFlags { None = 0, @@ -13015,6 +13016,7 @@ declare namespace ts { skipArkTSStaticBlocksCheck: boolean; constructor(sourceFile: SourceFile, tsProgram: Program, tscStrictDiagnostics?: Map | undefined); static clearTsTypeChecker(): void; + static clearQualifiedNameCache(): void; readonly handlersMap: ESMap void>; incrementCounters(node: Node | CommentRange, faultId: number, autofixable?: boolean, autofix?: Autofix[]): void; visitTSNode(node: Node): void; @@ -13633,6 +13635,7 @@ declare namespace ts { private compatibleSdkVersion; constructor(sourceFile: SourceFile, tsProgram: Program, tscStrictDiagnostics?: Map | undefined); static clearTsTypeChecker(): void; + static clearQualifiedNameCache(): void; readonly handlersMap: ESMap void; name: string; diff --git a/lib/tsserverlibrary.js b/lib/tsserverlibrary.js index 257543d839..65d0e784d1 100644 --- a/lib/tsserverlibrary.js +++ b/lib/tsserverlibrary.js @@ -52041,6 +52041,8 @@ var ts; var apparentArgumentCount; var constEnumRelate = new ts.Map(); var performanceFileName; + // Used only for linter, in non-strict typeChecker, it is always empty. + var qualifiedNameCache = new ts.Map(); // 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 @@ -52384,6 +52386,7 @@ var ts; getConstEnumRelate: function () { return constEnumRelate; }, clearConstEnumRelate: function () { constEnumRelate && constEnumRelate.clear(); }, deleteConstEnumRelate: function (path) { constEnumRelate && constEnumRelate.delete(path); }, + clearQualifiedNameCache: function () { qualifiedNameCache && qualifiedNameCache.clear(); }, }; function runWithInferenceBlockedFromSourceNode(node, fn) { var containingCall = ts.findAncestor(node, ts.isCallLikeExpression); @@ -54894,7 +54897,21 @@ var ts; } } function getFullyQualifiedName(symbol, containingLocation) { - return symbol.parent ? getFullyQualifiedName(symbol.parent, containingLocation) + "." + symbolToString(symbol) : symbolToString(symbol, containingLocation, /*meaning*/ undefined, 32 /* SymbolFormatFlags.DoNotIncludeSymbolChain */ | 4 /* SymbolFormatFlags.AllowAnyNodeKind */); + if (containingLocation === undefined) { + var cachedQualifiedName = qualifiedNameCache.get(symbol); + if (cachedQualifiedName) { + return cachedQualifiedName; + } + } + var qualifiedName = getFullyQualifiedNameNoCache(symbol, containingLocation); + if (isTypeCheckerForLinter && containingLocation === undefined) { + qualifiedNameCache.set(symbol, qualifiedName); + } + return qualifiedName; + } + function getFullyQualifiedNameNoCache(symbol, containingLocation) { + return symbol.parent ? getFullyQualifiedNameNoCache(symbol.parent, containingLocation) + "." + symbolToString(symbol) : + symbolToString(symbol, containingLocation, /*meaning*/ undefined, 32 /* SymbolFormatFlags.DoNotIncludeSymbolChain */ | 4 /* SymbolFormatFlags.AllowAnyNodeKind */); } function getContainingQualifiedNameNode(node) { while (ts.isQualifiedName(node.parent)) { @@ -192798,6 +192815,11 @@ var ts; TypeScriptLinter.clearTsTypeChecker = function () { TypeScriptLinter.tsTypeChecker = {}; }; + TypeScriptLinter.clearQualifiedNameCache = function () { + if (TypeScriptLinter.tsTypeChecker) { + TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache && TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache(); + } + }; TypeScriptLinter.prototype.incrementCounters = function (node, faultId, autofixable, autofix) { if (autofixable === void 0) { autofixable = false; } if (!TypeScriptLinter.strictMode && faultsAttrs[faultId].migratable) { @@ -194593,6 +194615,7 @@ var ts; ArkTSLinter_1_0.runArkTSLinter = runArkTSLinter; // reclaiming memory for Hvigor with "no-parallel" and "daemon", . function releaseReferences() { + ArkTSLinter_1_0.TypeScriptLinter.clearQualifiedNameCache(); ArkTSLinter_1_0.TypeScriptLinter.clearTsTypeChecker(); ArkTSLinter_1_0.Utils.clearTypeChecker(); ArkTSLinter_1_0.Utils.clearTrueSymbolAtLocationCache(); @@ -198204,6 +198227,11 @@ var ts; TypeScriptLinter.clearTsTypeChecker = function () { TypeScriptLinter.tsTypeChecker = {}; }; + TypeScriptLinter.clearQualifiedNameCache = function () { + if (TypeScriptLinter.tsTypeChecker) { + TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache && TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache(); + } + }; TypeScriptLinter.prototype.incrementCounters = function (node, faultId, autofixable, autofix) { var _a, _b; if (autofixable === void 0) { autofixable = false; } @@ -201029,6 +201057,7 @@ var ts; ArkTSLinter_1_1.runArkTSLinter = runArkTSLinter; // reclaiming memory for Hvigor with "no-parallel" and "daemon", . function releaseReferences() { + ArkTSLinter_1_1.TypeScriptLinter.clearQualifiedNameCache(); ArkTSLinter_1_1.TypeScriptLinter.clearTsTypeChecker(); ArkTSLinter_1_1.InteropTypescriptLinter.clearTsTypeChecker(); ArkTSLinter_1_1.Utils.clearTypeChecker(); diff --git a/lib/typescript.d.ts b/lib/typescript.d.ts index 7d6cfa89e4..ce41ad5ba4 100644 --- a/lib/typescript.d.ts +++ b/lib/typescript.d.ts @@ -2543,6 +2543,7 @@ declare namespace ts { getConstEnumRelate?(): ESMap>; clearConstEnumRelate?(): void; deleteConstEnumRelate?(path: string): void; + clearQualifiedNameCache?(): void; } export enum NodeBuilderFlags { None = 0, @@ -9069,6 +9070,7 @@ declare namespace ts { skipArkTSStaticBlocksCheck: boolean; constructor(sourceFile: SourceFile, tsProgram: Program, tscStrictDiagnostics?: Map | undefined); static clearTsTypeChecker(): void; + static clearQualifiedNameCache(): void; readonly handlersMap: ESMap void>; incrementCounters(node: Node | CommentRange, faultId: number, autofixable?: boolean, autofix?: Autofix[]): void; visitTSNode(node: Node): void; @@ -9687,6 +9689,7 @@ declare namespace ts { private compatibleSdkVersion; constructor(sourceFile: SourceFile, tsProgram: Program, tscStrictDiagnostics?: Map | undefined); static clearTsTypeChecker(): void; + static clearQualifiedNameCache(): void; readonly handlersMap: ESMap void; name: string; diff --git a/lib/typescript.js b/lib/typescript.js index 0230549835..3b0785a504 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -52032,6 +52032,8 @@ var ts; var apparentArgumentCount; var constEnumRelate = new ts.Map(); var performanceFileName; + // Used only for linter, in non-strict typeChecker, it is always empty. + var qualifiedNameCache = new ts.Map(); // 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 @@ -52375,6 +52377,7 @@ var ts; getConstEnumRelate: function () { return constEnumRelate; }, clearConstEnumRelate: function () { constEnumRelate && constEnumRelate.clear(); }, deleteConstEnumRelate: function (path) { constEnumRelate && constEnumRelate.delete(path); }, + clearQualifiedNameCache: function () { qualifiedNameCache && qualifiedNameCache.clear(); }, }; function runWithInferenceBlockedFromSourceNode(node, fn) { var containingCall = ts.findAncestor(node, ts.isCallLikeExpression); @@ -54885,7 +54888,21 @@ var ts; } } function getFullyQualifiedName(symbol, containingLocation) { - return symbol.parent ? getFullyQualifiedName(symbol.parent, containingLocation) + "." + symbolToString(symbol) : symbolToString(symbol, containingLocation, /*meaning*/ undefined, 32 /* SymbolFormatFlags.DoNotIncludeSymbolChain */ | 4 /* SymbolFormatFlags.AllowAnyNodeKind */); + if (containingLocation === undefined) { + var cachedQualifiedName = qualifiedNameCache.get(symbol); + if (cachedQualifiedName) { + return cachedQualifiedName; + } + } + var qualifiedName = getFullyQualifiedNameNoCache(symbol, containingLocation); + if (isTypeCheckerForLinter && containingLocation === undefined) { + qualifiedNameCache.set(symbol, qualifiedName); + } + return qualifiedName; + } + function getFullyQualifiedNameNoCache(symbol, containingLocation) { + return symbol.parent ? getFullyQualifiedNameNoCache(symbol.parent, containingLocation) + "." + symbolToString(symbol) : + symbolToString(symbol, containingLocation, /*meaning*/ undefined, 32 /* SymbolFormatFlags.DoNotIncludeSymbolChain */ | 4 /* SymbolFormatFlags.AllowAnyNodeKind */); } function getContainingQualifiedNameNode(node) { while (ts.isQualifiedName(node.parent)) { @@ -181892,6 +181909,11 @@ var ts; TypeScriptLinter.clearTsTypeChecker = function () { TypeScriptLinter.tsTypeChecker = {}; }; + TypeScriptLinter.clearQualifiedNameCache = function () { + if (TypeScriptLinter.tsTypeChecker) { + TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache && TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache(); + } + }; TypeScriptLinter.prototype.incrementCounters = function (node, faultId, autofixable, autofix) { if (autofixable === void 0) { autofixable = false; } if (!TypeScriptLinter.strictMode && faultsAttrs[faultId].migratable) { @@ -183687,6 +183709,7 @@ var ts; ArkTSLinter_1_0.runArkTSLinter = runArkTSLinter; // reclaiming memory for Hvigor with "no-parallel" and "daemon", . function releaseReferences() { + ArkTSLinter_1_0.TypeScriptLinter.clearQualifiedNameCache(); ArkTSLinter_1_0.TypeScriptLinter.clearTsTypeChecker(); ArkTSLinter_1_0.Utils.clearTypeChecker(); ArkTSLinter_1_0.Utils.clearTrueSymbolAtLocationCache(); @@ -187298,6 +187321,11 @@ var ts; TypeScriptLinter.clearTsTypeChecker = function () { TypeScriptLinter.tsTypeChecker = {}; }; + TypeScriptLinter.clearQualifiedNameCache = function () { + if (TypeScriptLinter.tsTypeChecker) { + TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache && TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache(); + } + }; TypeScriptLinter.prototype.incrementCounters = function (node, faultId, autofixable, autofix) { var _a, _b; if (autofixable === void 0) { autofixable = false; } @@ -190123,6 +190151,7 @@ var ts; ArkTSLinter_1_1.runArkTSLinter = runArkTSLinter; // reclaiming memory for Hvigor with "no-parallel" and "daemon", . function releaseReferences() { + ArkTSLinter_1_1.TypeScriptLinter.clearQualifiedNameCache(); ArkTSLinter_1_1.TypeScriptLinter.clearTsTypeChecker(); ArkTSLinter_1_1.InteropTypescriptLinter.clearTsTypeChecker(); ArkTSLinter_1_1.Utils.clearTypeChecker(); diff --git a/lib/typescriptServices.d.ts b/lib/typescriptServices.d.ts index a69ea55548..efcf2daeb0 100644 --- a/lib/typescriptServices.d.ts +++ b/lib/typescriptServices.d.ts @@ -2543,6 +2543,7 @@ declare namespace ts { getConstEnumRelate?(): ESMap>; clearConstEnumRelate?(): void; deleteConstEnumRelate?(path: string): void; + clearQualifiedNameCache?(): void; } export enum NodeBuilderFlags { None = 0, @@ -9069,6 +9070,7 @@ declare namespace ts { skipArkTSStaticBlocksCheck: boolean; constructor(sourceFile: SourceFile, tsProgram: Program, tscStrictDiagnostics?: Map | undefined); static clearTsTypeChecker(): void; + static clearQualifiedNameCache(): void; readonly handlersMap: ESMap void>; incrementCounters(node: Node | CommentRange, faultId: number, autofixable?: boolean, autofix?: Autofix[]): void; visitTSNode(node: Node): void; @@ -9687,6 +9689,7 @@ declare namespace ts { private compatibleSdkVersion; constructor(sourceFile: SourceFile, tsProgram: Program, tscStrictDiagnostics?: Map | undefined); static clearTsTypeChecker(): void; + static clearQualifiedNameCache(): void; readonly handlersMap: ESMap void; name: string; diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js index 16c68c26e2..52606bf025 100644 --- a/lib/typescriptServices.js +++ b/lib/typescriptServices.js @@ -52032,6 +52032,8 @@ var ts; var apparentArgumentCount; var constEnumRelate = new ts.Map(); var performanceFileName; + // Used only for linter, in non-strict typeChecker, it is always empty. + var qualifiedNameCache = new ts.Map(); // 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 @@ -52375,6 +52377,7 @@ var ts; getConstEnumRelate: function () { return constEnumRelate; }, clearConstEnumRelate: function () { constEnumRelate && constEnumRelate.clear(); }, deleteConstEnumRelate: function (path) { constEnumRelate && constEnumRelate.delete(path); }, + clearQualifiedNameCache: function () { qualifiedNameCache && qualifiedNameCache.clear(); }, }; function runWithInferenceBlockedFromSourceNode(node, fn) { var containingCall = ts.findAncestor(node, ts.isCallLikeExpression); @@ -54885,7 +54888,21 @@ var ts; } } function getFullyQualifiedName(symbol, containingLocation) { - return symbol.parent ? getFullyQualifiedName(symbol.parent, containingLocation) + "." + symbolToString(symbol) : symbolToString(symbol, containingLocation, /*meaning*/ undefined, 32 /* SymbolFormatFlags.DoNotIncludeSymbolChain */ | 4 /* SymbolFormatFlags.AllowAnyNodeKind */); + if (containingLocation === undefined) { + var cachedQualifiedName = qualifiedNameCache.get(symbol); + if (cachedQualifiedName) { + return cachedQualifiedName; + } + } + var qualifiedName = getFullyQualifiedNameNoCache(symbol, containingLocation); + if (isTypeCheckerForLinter && containingLocation === undefined) { + qualifiedNameCache.set(symbol, qualifiedName); + } + return qualifiedName; + } + function getFullyQualifiedNameNoCache(symbol, containingLocation) { + return symbol.parent ? getFullyQualifiedNameNoCache(symbol.parent, containingLocation) + "." + symbolToString(symbol) : + symbolToString(symbol, containingLocation, /*meaning*/ undefined, 32 /* SymbolFormatFlags.DoNotIncludeSymbolChain */ | 4 /* SymbolFormatFlags.AllowAnyNodeKind */); } function getContainingQualifiedNameNode(node) { while (ts.isQualifiedName(node.parent)) { @@ -181892,6 +181909,11 @@ var ts; TypeScriptLinter.clearTsTypeChecker = function () { TypeScriptLinter.tsTypeChecker = {}; }; + TypeScriptLinter.clearQualifiedNameCache = function () { + if (TypeScriptLinter.tsTypeChecker) { + TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache && TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache(); + } + }; TypeScriptLinter.prototype.incrementCounters = function (node, faultId, autofixable, autofix) { if (autofixable === void 0) { autofixable = false; } if (!TypeScriptLinter.strictMode && faultsAttrs[faultId].migratable) { @@ -183687,6 +183709,7 @@ var ts; ArkTSLinter_1_0.runArkTSLinter = runArkTSLinter; // reclaiming memory for Hvigor with "no-parallel" and "daemon", . function releaseReferences() { + ArkTSLinter_1_0.TypeScriptLinter.clearQualifiedNameCache(); ArkTSLinter_1_0.TypeScriptLinter.clearTsTypeChecker(); ArkTSLinter_1_0.Utils.clearTypeChecker(); ArkTSLinter_1_0.Utils.clearTrueSymbolAtLocationCache(); @@ -187298,6 +187321,11 @@ var ts; TypeScriptLinter.clearTsTypeChecker = function () { TypeScriptLinter.tsTypeChecker = {}; }; + TypeScriptLinter.clearQualifiedNameCache = function () { + if (TypeScriptLinter.tsTypeChecker) { + TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache && TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache(); + } + }; TypeScriptLinter.prototype.incrementCounters = function (node, faultId, autofixable, autofix) { var _a, _b; if (autofixable === void 0) { autofixable = false; } @@ -190123,6 +190151,7 @@ var ts; ArkTSLinter_1_1.runArkTSLinter = runArkTSLinter; // reclaiming memory for Hvigor with "no-parallel" and "daemon", . function releaseReferences() { + ArkTSLinter_1_1.TypeScriptLinter.clearQualifiedNameCache(); ArkTSLinter_1_1.TypeScriptLinter.clearTsTypeChecker(); ArkTSLinter_1_1.InteropTypescriptLinter.clearTsTypeChecker(); ArkTSLinter_1_1.Utils.clearTypeChecker(); diff --git a/lib/typingsInstaller.js b/lib/typingsInstaller.js index e2cfecc552..d7a5353268 100644 --- a/lib/typingsInstaller.js +++ b/lib/typingsInstaller.js @@ -52022,6 +52022,8 @@ var ts; var apparentArgumentCount; var constEnumRelate = new ts.Map(); var performanceFileName; + // Used only for linter, in non-strict typeChecker, it is always empty. + var qualifiedNameCache = new ts.Map(); // 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 @@ -52365,6 +52367,7 @@ var ts; getConstEnumRelate: function () { return constEnumRelate; }, clearConstEnumRelate: function () { constEnumRelate && constEnumRelate.clear(); }, deleteConstEnumRelate: function (path) { constEnumRelate && constEnumRelate.delete(path); }, + clearQualifiedNameCache: function () { qualifiedNameCache && qualifiedNameCache.clear(); }, }; function runWithInferenceBlockedFromSourceNode(node, fn) { var containingCall = ts.findAncestor(node, ts.isCallLikeExpression); @@ -54875,7 +54878,21 @@ var ts; } } function getFullyQualifiedName(symbol, containingLocation) { - return symbol.parent ? getFullyQualifiedName(symbol.parent, containingLocation) + "." + symbolToString(symbol) : symbolToString(symbol, containingLocation, /*meaning*/ undefined, 32 /* SymbolFormatFlags.DoNotIncludeSymbolChain */ | 4 /* SymbolFormatFlags.AllowAnyNodeKind */); + if (containingLocation === undefined) { + var cachedQualifiedName = qualifiedNameCache.get(symbol); + if (cachedQualifiedName) { + return cachedQualifiedName; + } + } + var qualifiedName = getFullyQualifiedNameNoCache(symbol, containingLocation); + if (isTypeCheckerForLinter && containingLocation === undefined) { + qualifiedNameCache.set(symbol, qualifiedName); + } + return qualifiedName; + } + function getFullyQualifiedNameNoCache(symbol, containingLocation) { + return symbol.parent ? getFullyQualifiedNameNoCache(symbol.parent, containingLocation) + "." + symbolToString(symbol) : + symbolToString(symbol, containingLocation, /*meaning*/ undefined, 32 /* SymbolFormatFlags.DoNotIncludeSymbolChain */ | 4 /* SymbolFormatFlags.AllowAnyNodeKind */); } function getContainingQualifiedNameNode(node) { while (ts.isQualifiedName(node.parent)) { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e8504920ae..0e34384675 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -408,6 +408,8 @@ namespace ts { let constEnumRelate: ESMap> = new Map(); let performanceFileName: string; + // Used only for linter, in non-strict typeChecker, it is always empty. + let qualifiedNameCache: ESMap = new Map(); // for public members that accept a Node or one of its subtypes, we must guard against // synthetic nodes created during transformations by calling `getParseTreeNode`. @@ -763,6 +765,7 @@ namespace ts { getConstEnumRelate: () => constEnumRelate, clearConstEnumRelate: () => {constEnumRelate && constEnumRelate.clear()}, deleteConstEnumRelate: (path: string) => {constEnumRelate && constEnumRelate.delete(path)}, + clearQualifiedNameCache: () => {qualifiedNameCache && qualifiedNameCache.clear()}, }; function runWithInferenceBlockedFromSourceNode(node: Node | undefined, fn: () => T): T { @@ -3503,7 +3506,23 @@ namespace ts { } function getFullyQualifiedName(symbol: Symbol, containingLocation?: Node): string { - return symbol.parent ? getFullyQualifiedName(symbol.parent, containingLocation) + "." + symbolToString(symbol) : symbolToString(symbol, containingLocation, /*meaning*/ undefined, SymbolFormatFlags.DoNotIncludeSymbolChain | SymbolFormatFlags.AllowAnyNodeKind); + if (containingLocation === undefined) { + const cachedQualifiedName: string | undefined = qualifiedNameCache.get(symbol); + if (cachedQualifiedName) { + return cachedQualifiedName; + } + } + let qualifiedName: string = getFullyQualifiedNameNoCache(symbol, containingLocation); + if (isTypeCheckerForLinter && containingLocation === undefined) { + qualifiedNameCache.set(symbol, qualifiedName); + } + return qualifiedName; + } + + function getFullyQualifiedNameNoCache(symbol: Symbol, containingLocation?: Node): string { + return symbol.parent ? getFullyQualifiedNameNoCache(symbol.parent, containingLocation) + "." + symbolToString(symbol) : + symbolToString(symbol, containingLocation, /*meaning*/ undefined, + SymbolFormatFlags.DoNotIncludeSymbolChain | SymbolFormatFlags.AllowAnyNodeKind); } function getContainingQualifiedNameNode(node: QualifiedName) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 79b63a7aa7..dae0325c65 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4984,6 +4984,7 @@ namespace ts { getConstEnumRelate?(): ESMap>; clearConstEnumRelate?(): void; deleteConstEnumRelate?(path: string): void; + clearQualifiedNameCache?(): void; } /* @internal */ diff --git a/src/linter/ArkTSLinter_1_0/LinterRunner.ts b/src/linter/ArkTSLinter_1_0/LinterRunner.ts index d17dc70555..3e1405286c 100644 --- a/src/linter/ArkTSLinter_1_0/LinterRunner.ts +++ b/src/linter/ArkTSLinter_1_0/LinterRunner.ts @@ -106,6 +106,7 @@ export function runArkTSLinter(tsBuilderProgram: BuilderProgram, srcFile?: Sourc // reclaiming memory for Hvigor with "no-parallel" and "daemon", . function releaseReferences(): void { + TypeScriptLinter.clearQualifiedNameCache(); TypeScriptLinter.clearTsTypeChecker(); Utils.clearTypeChecker(); Utils.clearTrueSymbolAtLocationCache(); diff --git a/src/linter/ArkTSLinter_1_0/TypeScriptLinter.ts b/src/linter/ArkTSLinter_1_0/TypeScriptLinter.ts index 6a04ffdbeb..cab1536ed4 100644 --- a/src/linter/ArkTSLinter_1_0/TypeScriptLinter.ts +++ b/src/linter/ArkTSLinter_1_0/TypeScriptLinter.ts @@ -159,6 +159,12 @@ export class TypeScriptLinter { TypeScriptLinter.tsTypeChecker = {} as TypeChecker; } + public static clearQualifiedNameCache(): void { + if (TypeScriptLinter.tsTypeChecker) { + TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache && TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache(); + } + } + readonly handlersMap = new Map([ [SyntaxKind.ObjectLiteralExpression, this.handleObjectLiteralExpression], [SyntaxKind.ArrayLiteralExpression, this.handleArrayLiteralExpression], diff --git a/src/linter/ArkTSLinter_1_1/LinterRunner.ts b/src/linter/ArkTSLinter_1_1/LinterRunner.ts index 44b7f45bef..f25ac8dcb2 100644 --- a/src/linter/ArkTSLinter_1_1/LinterRunner.ts +++ b/src/linter/ArkTSLinter_1_1/LinterRunner.ts @@ -144,6 +144,7 @@ export function runArkTSLinter(tsBuilderProgram: BuilderProgram, srcFile?: Sourc // reclaiming memory for Hvigor with "no-parallel" and "daemon", . function releaseReferences(): void { + TypeScriptLinter.clearQualifiedNameCache(); TypeScriptLinter.clearTsTypeChecker(); InteropTypescriptLinter.clearTsTypeChecker(); Utils.clearTypeChecker(); diff --git a/src/linter/ArkTSLinter_1_1/TypeScriptLinter.ts b/src/linter/ArkTSLinter_1_1/TypeScriptLinter.ts index 1aad039431..aa19f0b4c8 100644 --- a/src/linter/ArkTSLinter_1_1/TypeScriptLinter.ts +++ b/src/linter/ArkTSLinter_1_1/TypeScriptLinter.ts @@ -163,6 +163,12 @@ export class TypeScriptLinter { TypeScriptLinter.tsTypeChecker = {} as TypeChecker; } + public static clearQualifiedNameCache(): void { + if (TypeScriptLinter.tsTypeChecker) { + TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache && TypeScriptLinter.tsTypeChecker.clearQualifiedNameCache(); + } + } + readonly handlersMap = new Map([ [SyntaxKind.ObjectLiteralExpression, {handler: this.handleObjectLiteralExpression, name: 'handleObjectLiteralExpression'}], [SyntaxKind.ArrayLiteralExpression, {handler: this.handleArrayLiteralExpression, name: 'handleArrayLiteralExpression'}], diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index e492286d6d..a07c00f2a5 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2543,6 +2543,7 @@ declare namespace ts { getConstEnumRelate?(): ESMap>; clearConstEnumRelate?(): void; deleteConstEnumRelate?(path: string): void; + clearQualifiedNameCache?(): void; } export enum NodeBuilderFlags { None = 0, @@ -13015,6 +13016,7 @@ declare namespace ts { skipArkTSStaticBlocksCheck: boolean; constructor(sourceFile: SourceFile, tsProgram: Program, tscStrictDiagnostics?: Map | undefined); static clearTsTypeChecker(): void; + static clearQualifiedNameCache(): void; readonly handlersMap: ESMap void>; incrementCounters(node: Node | CommentRange, faultId: number, autofixable?: boolean, autofix?: Autofix[]): void; visitTSNode(node: Node): void; @@ -13633,6 +13635,7 @@ declare namespace ts { private compatibleSdkVersion; constructor(sourceFile: SourceFile, tsProgram: Program, tscStrictDiagnostics?: Map | undefined); static clearTsTypeChecker(): void; + static clearQualifiedNameCache(): void; readonly handlersMap: ESMap void; name: string; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 7d6cfa89e4..ce41ad5ba4 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2543,6 +2543,7 @@ declare namespace ts { getConstEnumRelate?(): ESMap>; clearConstEnumRelate?(): void; deleteConstEnumRelate?(path: string): void; + clearQualifiedNameCache?(): void; } export enum NodeBuilderFlags { None = 0, @@ -9069,6 +9070,7 @@ declare namespace ts { skipArkTSStaticBlocksCheck: boolean; constructor(sourceFile: SourceFile, tsProgram: Program, tscStrictDiagnostics?: Map | undefined); static clearTsTypeChecker(): void; + static clearQualifiedNameCache(): void; readonly handlersMap: ESMap void>; incrementCounters(node: Node | CommentRange, faultId: number, autofixable?: boolean, autofix?: Autofix[]): void; visitTSNode(node: Node): void; @@ -9687,6 +9689,7 @@ declare namespace ts { private compatibleSdkVersion; constructor(sourceFile: SourceFile, tsProgram: Program, tscStrictDiagnostics?: Map | undefined); static clearTsTypeChecker(): void; + static clearQualifiedNameCache(): void; readonly handlersMap: ESMap void; name: string; -- Gitee From 3c27e42ec0223727993faffc729912102f40f3bc Mon Sep 17 00:00:00 2001 From: zengyuan Date: Mon, 17 Feb 2025 11:27:31 +0800 Subject: [PATCH 3/3] cherrt-pick performance features --- lib/tsc.js | 82 ++++++++++++++++++------ lib/tsserver.js | 114 ++++++++++++++++++++++++---------- lib/tsserverlibrary.js | 114 ++++++++++++++++++++++++---------- lib/typescript.js | 114 ++++++++++++++++++++++++---------- lib/typescriptServices.js | 114 ++++++++++++++++++++++++---------- lib/typingsInstaller.js | 95 +++++++++++++++++++++------- src/compiler/binder.ts | 47 +++++++++++--- src/compiler/checker.ts | 36 +++++++---- src/compiler/emitter.ts | 12 ++++ src/compiler/types.ts | 2 +- src/services/callHierarchy.ts | 2 +- src/services/inlayHints.ts | 3 +- src/services/signatureHelp.ts | 6 +- src/services/symbolDisplay.ts | 6 +- src/services/utilities.ts | 2 +- 15 files changed, 538 insertions(+), 211 deletions(-) diff --git a/lib/tsc.js b/lib/tsc.js index b33c904480..ef77c0fa69 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -39913,6 +39913,7 @@ var ts; var preSwitchCaseFlow; var activeLabelList; var hasExplicitReturn; + var hasFlowEffects; var emitFlags; var inStrictMode; var inAssignmentPattern = false; @@ -39964,6 +39965,7 @@ var ts; currentExceptionTarget = undefined; activeLabelList = undefined; hasExplicitReturn = false; + hasFlowEffects = false; inAssignmentPattern = false; emitFlags = 0; } @@ -40411,8 +40413,8 @@ var ts; function isNarrowingExpression(expr) { switch (expr.kind) { case 79: - case 80: case 109: + return true; case 211: case 212: return containsNarrowableReference(expr); @@ -40431,11 +40433,24 @@ var ts; return false; } function isNarrowableReference(expr) { - return ts.isDottedName(expr) - || (ts.isPropertyAccessExpression(expr) || ts.isNonNullExpression(expr) || ts.isParenthesizedExpression(expr)) && isNarrowableReference(expr.expression) - || ts.isBinaryExpression(expr) && expr.operatorToken.kind === 27 && isNarrowableReference(expr.right) - || ts.isElementAccessExpression(expr) && (ts.isStringOrNumericLiteralLike(expr.argumentExpression) || ts.isEntityNameExpression(expr.argumentExpression)) && isNarrowableReference(expr.expression) - || ts.isAssignmentExpression(expr) && isNarrowableReference(expr.left); + switch (expr.kind) { + case 79: + case 109: + case 107: + case 237: + return true; + case 211: + case 217: + case 236: + return isNarrowableReference(expr.expression); + case 212: + return (ts.isStringOrNumericLiteralLike(expr.argumentExpression) || ts.isEntityNameExpression(expr.argumentExpression)) && + isNarrowableReference(expr.expression); + case 227: + return expr.operatorToken.kind === 27 && isNarrowableReference(expr.right) || + ts.isAssignmentOperator(expr.operatorToken.kind) && ts.isLeftHandSideExpression(expr.left); + } + return false; } function containsNarrowableReference(expr) { return isNarrowableReference(expr) || ts.isOptionalChain(expr) && containsNarrowableReference(expr.expression); @@ -40536,6 +40551,7 @@ var ts; } function createFlowMutation(flags, antecedent, node) { setFlowNodeReferenced(antecedent); + hasFlowEffects = true; var result = initFlowNode({ flags: flags, antecedent: antecedent, node: node }); if (currentExceptionTarget) { addAntecedent(currentExceptionTarget, result); @@ -40544,6 +40560,7 @@ var ts; } function createFlowCall(antecedent, node) { setFlowNodeReferenced(antecedent); + hasFlowEffects = true; return initFlowNode({ flags: 512, antecedent: antecedent, node: node }); } function finishFlowLabel(flow) { @@ -40709,6 +40726,7 @@ var ts; } } currentFlow = unreachableFlow; + hasFlowEffects = true; } function findActiveLabel(name) { for (var label = activeLabelList; label; label = label.next) { @@ -40723,6 +40741,7 @@ var ts; if (flowLabel) { addAntecedent(flowLabel, currentFlow); currentFlow = unreachableFlow; + hasFlowEffects = true; } } function bindBreakOrContinueStatement(node) { @@ -40986,8 +41005,12 @@ var ts; ts.isLogicalOrCoalescingAssignmentOperator(operator)) { if (isTopLevelLogicalExpression(node)) { var postExpressionLabel = createBranchLabel(); + var saveCurrentFlow = currentFlow; + var saveHasFlowEffects = hasFlowEffects; + hasFlowEffects = false; bindLogicalLikeExpression(node, postExpressionLabel, postExpressionLabel); - currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects || (hasFlowEffects = saveHasFlowEffects); } else { bindLogicalLikeExpression(node, currentTrueTarget, currentFalseTarget); @@ -41060,6 +41083,9 @@ var ts; var trueLabel = createBranchLabel(); var falseLabel = createBranchLabel(); var postExpressionLabel = createBranchLabel(); + var saveCurrentFlow = currentFlow; + var saveHasFlowEffects = hasFlowEffects; + hasFlowEffects = false; bindCondition(node.condition, trueLabel, falseLabel); currentFlow = finishFlowLabel(trueLabel); bind(node.questionToken); @@ -41070,6 +41096,8 @@ var ts; bind(node.whenFalse); addAntecedent(postExpressionLabel, currentFlow); currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects || (hasFlowEffects = saveHasFlowEffects); } function bindInitializedVariableFlow(node) { var name = !ts.isOmittedExpression(node) ? node.name : undefined; @@ -41173,8 +41201,11 @@ var ts; function bindOptionalChainFlow(node) { if (isTopLevelLogicalExpression(node)) { var postExpressionLabel = createBranchLabel(); + var saveCurrentFlow = currentFlow; + var saveHasFlowEffects = hasFlowEffects; bindOptionalChain(node, postExpressionLabel, postExpressionLabel); - currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects || (hasFlowEffects = saveHasFlowEffects); } else { bindOptionalChain(node, currentTrueTarget, currentFalseTarget); @@ -46582,7 +46613,9 @@ var ts; return writer ? symbolToStringWorker(writer).getText() : ts.usingSingleLineStringWriter(symbolToStringWorker); function symbolToStringWorker(writer) { var entity = builder(symbol, meaning, enclosingDeclaration, nodeFlags); - var printer = (enclosingDeclaration === null || enclosingDeclaration === void 0 ? void 0 : enclosingDeclaration.kind) === 314 ? ts.createPrinter({ removeComments: true, neverAsciiEscape: true }) : ts.createPrinter({ removeComments: true }); + var printer = (enclosingDeclaration === null || enclosingDeclaration === void 0 ? void 0 : enclosingDeclaration.kind) === 314 + ? ts.createPrinterWithRemoveCommentsNeverAsciiEscape() + : ts.createPrinterWithRemoveComments(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4, entity, sourceFile, writer); return writer; @@ -46600,7 +46633,7 @@ var ts; sigOutput = kind === 1 ? 180 : 179; } var sig = nodeBuilder.signatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, toNodeBuilderFlags(flags) | 70221824 | 512); - var printer = ts.createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + var printer = ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4, sig, sourceFile, ts.getTrailingSemicolonDeferringWriter(writer)); return writer; @@ -46613,8 +46646,7 @@ var ts; var typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | 70221824 | (noTruncation ? 1 : 0), writer); if (typeNode === undefined) return ts.Debug.fail("should always get typenode"); - var options = { removeComments: type !== unresolvedType }; - var printer = ts.createPrinter(options); + var printer = type !== unresolvedType ? ts.createPrinterWithRemoveComments() : ts.createPrinterWithDefaults(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4, typeNode, sourceFile, writer); var result = writer.getText(); @@ -49299,7 +49331,7 @@ var ts; return writer ? typePredicateToStringWorker(writer).getText() : ts.usingSingleLineStringWriter(typePredicateToStringWorker); function typePredicateToStringWorker(writer) { var predicate = ts.factory.createTypePredicateNode(typePredicate.kind === 2 || typePredicate.kind === 3 ? ts.factory.createToken(130) : undefined, typePredicate.kind === 1 || typePredicate.kind === 3 ? ts.factory.createIdentifier(typePredicate.parameterName) : ts.factory.createThisTypeNode(), typePredicate.type && nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | 70221824 | 512)); - var printer = ts.createPrinter({ removeComments: true }); + var printer = ts.createPrinterWithRemoveComments(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4, predicate, sourceFile, writer); return writer; @@ -54681,7 +54713,7 @@ var ts; origin = createOriginUnionOrIntersectionType(1048576, reducedTypes); } } - var objectFlags = (includes & 36323363 ? 0 : 32768) | + var objectFlags = (includes & 36323331 ? 0 : 32768) | (includes & 2097152 ? 16777216 : 0); return getUnionTypeFromSortedList(typeSet, objectFlags, aliasSymbol, aliasTypeArguments, origin); } @@ -54814,7 +54846,7 @@ var ts; var u = unionTypes_1[_i]; if (!containsType(u.types, type)) { var primitive = type.flags & 128 ? stringType : - type.flags & 256 ? numberType : + type.flags & (32 | 256) ? numberType : type.flags & 2048 ? bigintType : type.flags & 8192 ? esSymbolType : undefined; @@ -54846,9 +54878,6 @@ var ts; } return false; } - function eachIsUnionContaining(types, flag) { - return ts.every(types, function (t) { return !!(t.flags & 1048576) && ts.some(t.types, function (tt) { return !!(tt.flags & flag); }); }); - } function removeFromEach(types, flag) { for (var i = 0; i < types.length; i++) { types[i] = filterType(types[i], function (t) { return !(t.flags & flag); }); @@ -54948,12 +54977,12 @@ var ts; if (intersectUnionsOfPrimitiveTypes(typeSet)) { result = getIntersectionType(typeSet, aliasSymbol, aliasTypeArguments); } - else if (eachIsUnionContaining(typeSet, 32768)) { + else if (ts.every(typeSet, function (t) { return !!(t.flags & 1048576 && t.types[0].flags & 32768); })) { var undefinedOrMissingType = exactOptionalPropertyTypes && ts.some(typeSet, function (t) { return containsType(t.types, missingType); }) ? missingType : undefinedType; removeFromEach(typeSet, 32768); result = getUnionType([getIntersectionType(typeSet), undefinedOrMissingType], 1, aliasSymbol, aliasTypeArguments); } - else if (eachIsUnionContaining(typeSet, 65536)) { + else if (ts.every(typeSet, function (t) { return !!(t.flags & 1048576 && (t.types[0].flags & 65536 || t.types[1].flags & 65536)); })) { removeFromEach(typeSet, 65536); result = getUnionType([getIntersectionType(typeSet), nullType], 1, aliasSymbol, aliasTypeArguments); } @@ -58295,6 +58324,15 @@ var ts; if (containsType(targetTypes, source)) { return -1; } + if (ts.getObjectFlags(target) & 32768 && !(source.flags & 1024) && (source.flags & (128 | 512 | 2048) || + (relation === subtypeRelation || relation === strictSubtypeRelation) && source.flags & 256)) { + var alternateForm = source === source.regularType ? source.freshType : source.regularType; + var primitive = source.flags & 128 ? stringType : + source.flags & 256 ? numberType : + source.flags & 2048 ? bigintType : + undefined; + return primitive && containsType(targetTypes, primitive) || alternateForm && containsType(targetTypes, alternateForm) ? -1 : 0; + } var match = getMatchingUnionConstituentForType(target, source); if (match) { var related = isRelatedTo(source, match, 2, false); @@ -97135,6 +97173,10 @@ var ts; return outputFiles; } ts.emitUsingBuildInfo = emitUsingBuildInfo; + ts.createPrinterWithDefaults = ts.memoize(function () { return createPrinter({}); }); + ts.createPrinterWithRemoveComments = ts.memoize(function () { return createPrinter({ removeComments: true }); }); + ts.createPrinterWithRemoveCommentsNeverAsciiEscape = ts.memoize(function () { return createPrinter({ removeComments: true, neverAsciiEscape: true }); }); + ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon = ts.memoize(function () { return createPrinter({ removeComments: true, omitTrailingSemicolon: true }); }); function createPrinter(printerOptions, handlers) { if (printerOptions === void 0) { printerOptions = {}; } if (handlers === void 0) { handlers = {}; } diff --git a/lib/tsserver.js b/lib/tsserver.js index e67874d0a7..da6bd23e4f 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -5430,7 +5430,7 @@ var ts; /* @internal */ TypeFlags[TypeFlags["IncludesInstantiable"] = 33554432] = "IncludesInstantiable"; /* @internal */ - TypeFlags[TypeFlags["NotPrimitiveUnion"] = 36323363] = "NotPrimitiveUnion"; + TypeFlags[TypeFlags["NotPrimitiveUnion"] = 36323331] = "NotPrimitiveUnion"; })(TypeFlags = ts.TypeFlags || (ts.TypeFlags = {})); // Types included in TypeFlags.ObjectFlagsType have an objectFlags property. Some ObjectFlags // are specific to certain types and reuse the same bit position. Those ObjectFlags require a check @@ -39323,7 +39323,7 @@ var ts; return withJSDoc(finishNode(node, pos), hasJSDoc); } function isSetLazy(identifier) { - // 1. import lazy { export } from "mod"; + // 1. import lazy { export } from "mod"; // 2. import lazy defaultExport from "mod"; // 3. import lazy defaultExport, { export, /* ... */ } from "mod"; return (identifier === null || identifier === void 0 ? void 0 : identifier.escapedText) === 'lazy' && @@ -48427,6 +48427,7 @@ var ts; var preSwitchCaseFlow; var activeLabelList; var hasExplicitReturn; + var hasFlowEffects; // state used for emit helpers var emitFlags; // If this file is an external module, then it is automatically in strict-mode according to @@ -48490,6 +48491,7 @@ var ts; currentExceptionTarget = undefined; activeLabelList = undefined; hasExplicitReturn = false; + hasFlowEffects = false; inAssignmentPattern = false; emitFlags = 0 /* NodeFlags.None */; } @@ -49050,8 +49052,8 @@ var ts; function isNarrowingExpression(expr) { switch (expr.kind) { case 79 /* SyntaxKind.Identifier */: - case 80 /* SyntaxKind.PrivateIdentifier */: case 109 /* SyntaxKind.ThisKeyword */: + return true; case 211 /* SyntaxKind.PropertyAccessExpression */: case 212 /* SyntaxKind.ElementAccessExpression */: return containsNarrowableReference(expr); @@ -49070,11 +49072,24 @@ var ts; return false; } function isNarrowableReference(expr) { - return ts.isDottedName(expr) - || (ts.isPropertyAccessExpression(expr) || ts.isNonNullExpression(expr) || ts.isParenthesizedExpression(expr)) && isNarrowableReference(expr.expression) - || ts.isBinaryExpression(expr) && expr.operatorToken.kind === 27 /* SyntaxKind.CommaToken */ && isNarrowableReference(expr.right) - || ts.isElementAccessExpression(expr) && (ts.isStringOrNumericLiteralLike(expr.argumentExpression) || ts.isEntityNameExpression(expr.argumentExpression)) && isNarrowableReference(expr.expression) - || ts.isAssignmentExpression(expr) && isNarrowableReference(expr.left); + switch (expr.kind) { + case 79 /* SyntaxKind.Identifier */: + case 109 /* SyntaxKind.ThisKeyword */: + case 107 /* SyntaxKind.SuperKeyword */: + case 237 /* SyntaxKind.MetaProperty */: + return true; + case 211 /* SyntaxKind.PropertyAccessExpression */: + case 217 /* SyntaxKind.ParenthesizedExpression */: + case 236 /* SyntaxKind.NonNullExpression */: + return isNarrowableReference(expr.expression); + case 212 /* SyntaxKind.ElementAccessExpression */: + return (ts.isStringOrNumericLiteralLike(expr.argumentExpression) || ts.isEntityNameExpression(expr.argumentExpression)) && + isNarrowableReference(expr.expression); + case 227 /* SyntaxKind.BinaryExpression */: + return expr.operatorToken.kind === 27 /* SyntaxKind.CommaToken */ && isNarrowableReference(expr.right) || + ts.isAssignmentOperator(expr.operatorToken.kind) && ts.isLeftHandSideExpression(expr.left); + } + return false; } function containsNarrowableReference(expr) { return isNarrowableReference(expr) || ts.isOptionalChain(expr) && containsNarrowableReference(expr.expression); @@ -49176,6 +49191,7 @@ var ts; } function createFlowMutation(flags, antecedent, node) { setFlowNodeReferenced(antecedent); + hasFlowEffects = true; var result = initFlowNode({ flags: flags, antecedent: antecedent, node: node }); if (currentExceptionTarget) { addAntecedent(currentExceptionTarget, result); @@ -49184,6 +49200,7 @@ var ts; } function createFlowCall(antecedent, node) { setFlowNodeReferenced(antecedent); + hasFlowEffects = true; return initFlowNode({ flags: 512 /* FlowFlags.Call */, antecedent: antecedent, node: node }); } function finishFlowLabel(flow) { @@ -49349,6 +49366,7 @@ var ts; } } currentFlow = unreachableFlow; + hasFlowEffects = true; } function findActiveLabel(name) { for (var label = activeLabelList; label; label = label.next) { @@ -49363,6 +49381,7 @@ var ts; if (flowLabel) { addAntecedent(flowLabel, currentFlow); currentFlow = unreachableFlow; + hasFlowEffects = true; } } function bindBreakOrContinueStatement(node) { @@ -49668,8 +49687,12 @@ var ts; ts.isLogicalOrCoalescingAssignmentOperator(operator)) { if (isTopLevelLogicalExpression(node)) { var postExpressionLabel = createBranchLabel(); + var saveCurrentFlow = currentFlow; + var saveHasFlowEffects = hasFlowEffects; + hasFlowEffects = false; bindLogicalLikeExpression(node, postExpressionLabel, postExpressionLabel); - currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects || (hasFlowEffects = saveHasFlowEffects); } else { bindLogicalLikeExpression(node, currentTrueTarget, currentFalseTarget); @@ -49742,6 +49765,9 @@ var ts; var trueLabel = createBranchLabel(); var falseLabel = createBranchLabel(); var postExpressionLabel = createBranchLabel(); + var saveCurrentFlow = currentFlow; + var saveHasFlowEffects = hasFlowEffects; + hasFlowEffects = false; bindCondition(node.condition, trueLabel, falseLabel); currentFlow = finishFlowLabel(trueLabel); bind(node.questionToken); @@ -49752,6 +49778,8 @@ var ts; bind(node.whenFalse); addAntecedent(postExpressionLabel, currentFlow); currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects || (hasFlowEffects = saveHasFlowEffects); } function bindInitializedVariableFlow(node) { var name = !ts.isOmittedExpression(node) ? node.name : undefined; @@ -49873,8 +49901,11 @@ var ts; function bindOptionalChainFlow(node) { if (isTopLevelLogicalExpression(node)) { var postExpressionLabel = createBranchLabel(); + var saveCurrentFlow = currentFlow; + var saveHasFlowEffects = hasFlowEffects; bindOptionalChain(node, postExpressionLabel, postExpressionLabel); - currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects || (hasFlowEffects = saveHasFlowEffects); } else { bindOptionalChain(node, currentTrueTarget, currentFalseTarget); @@ -56278,7 +56309,9 @@ var ts; function symbolToStringWorker(writer) { var entity = builder(symbol, meaning, enclosingDeclaration, nodeFlags); // TODO: GH#18217 // add neverAsciiEscape for GH#39027 - var printer = (enclosingDeclaration === null || enclosingDeclaration === void 0 ? void 0 : enclosingDeclaration.kind) === 314 /* SyntaxKind.SourceFile */ ? ts.createPrinter({ removeComments: true, neverAsciiEscape: true }) : ts.createPrinter({ removeComments: true }); + var printer = (enclosingDeclaration === null || enclosingDeclaration === void 0 ? void 0 : enclosingDeclaration.kind) === 314 /* SyntaxKind.SourceFile */ + ? ts.createPrinterWithRemoveCommentsNeverAsciiEscape() + : ts.createPrinterWithRemoveComments(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, entity, /*sourceFile*/ sourceFile, writer); return writer; @@ -56296,7 +56329,7 @@ var ts; sigOutput = kind === 1 /* SignatureKind.Construct */ ? 180 /* SyntaxKind.ConstructSignature */ : 179 /* SyntaxKind.CallSignature */; } var sig = nodeBuilder.signatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, toNodeBuilderFlags(flags) | 70221824 /* NodeBuilderFlags.IgnoreErrors */ | 512 /* NodeBuilderFlags.WriteTypeParametersInQualifiedName */); - var printer = ts.createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + var printer = ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, sig, /*sourceFile*/ sourceFile, ts.getTrailingSemicolonDeferringWriter(writer)); // TODO: GH#18217 return writer; @@ -56311,8 +56344,7 @@ var ts; return ts.Debug.fail("should always get typenode"); // The unresolved type gets a synthesized comment on `any` to hint to users that it's not a plain `any`. // Otherwise, we always strip comments out. - var options = { removeComments: type !== unresolvedType }; - var printer = ts.createPrinter(options); + var printer = type !== unresolvedType ? ts.createPrinterWithRemoveComments() : ts.createPrinterWithDefaults(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, typeNode, /*sourceFile*/ sourceFile, writer); var result = writer.getText(); @@ -59388,7 +59420,7 @@ var ts; function typePredicateToStringWorker(writer) { var predicate = ts.factory.createTypePredicateNode(typePredicate.kind === 2 /* TypePredicateKind.AssertsThis */ || typePredicate.kind === 3 /* TypePredicateKind.AssertsIdentifier */ ? ts.factory.createToken(130 /* SyntaxKind.AssertsKeyword */) : undefined, typePredicate.kind === 1 /* TypePredicateKind.Identifier */ || typePredicate.kind === 3 /* TypePredicateKind.AssertsIdentifier */ ? ts.factory.createIdentifier(typePredicate.parameterName) : ts.factory.createThisTypeNode(), typePredicate.type && nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | 70221824 /* NodeBuilderFlags.IgnoreErrors */ | 512 /* NodeBuilderFlags.WriteTypeParametersInQualifiedName */) // TODO: GH#18217 ); - var printer = ts.createPrinter({ removeComments: true }); + var printer = ts.createPrinterWithRemoveComments(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, predicate, /*sourceFile*/ sourceFile, writer); return writer; @@ -65521,7 +65553,7 @@ var ts; origin = createOriginUnionOrIntersectionType(1048576 /* TypeFlags.Union */, reducedTypes); } } - var objectFlags = (includes & 36323363 /* TypeFlags.NotPrimitiveUnion */ ? 0 : 32768 /* ObjectFlags.PrimitiveUnion */) | + var objectFlags = (includes & 36323331 /* TypeFlags.NotPrimitiveUnion */ ? 0 : 32768 /* ObjectFlags.PrimitiveUnion */) | (includes & 2097152 /* TypeFlags.Intersection */ ? 16777216 /* ObjectFlags.ContainsIntersections */ : 0); return getUnionTypeFromSortedList(typeSet, objectFlags, aliasSymbol, aliasTypeArguments, origin); } @@ -65664,7 +65696,7 @@ var ts; var u = unionTypes_1[_i]; if (!containsType(u.types, type)) { var primitive = type.flags & 128 /* TypeFlags.StringLiteral */ ? stringType : - type.flags & 256 /* TypeFlags.NumberLiteral */ ? numberType : + type.flags & (32 /* TypeFlags.Enum */ | 256 /* TypeFlags.NumberLiteral */) ? numberType : type.flags & 2048 /* TypeFlags.BigIntLiteral */ ? bigintType : type.flags & 8192 /* TypeFlags.UniqueESSymbol */ ? esSymbolType : undefined; @@ -65700,9 +65732,6 @@ var ts; } return false; } - function eachIsUnionContaining(types, flag) { - return ts.every(types, function (t) { return !!(t.flags & 1048576 /* TypeFlags.Union */) && ts.some(t.types, function (tt) { return !!(tt.flags & flag); }); }); - } function removeFromEach(types, flag) { for (var i = 0; i < types.length; i++) { types[i] = filterType(types[i], function (t) { return !(t.flags & flag); }); @@ -65834,12 +65863,12 @@ var ts; // reduced we'll never reduce again, so this occurs at most once. result = getIntersectionType(typeSet, aliasSymbol, aliasTypeArguments); } - else if (eachIsUnionContaining(typeSet, 32768 /* TypeFlags.Undefined */)) { + else if (ts.every(typeSet, function (t) { return !!(t.flags & 1048576 /* TypeFlags.Union */ && t.types[0].flags & 32768 /* TypeFlags.Undefined */); })) { var undefinedOrMissingType = exactOptionalPropertyTypes && ts.some(typeSet, function (t) { return containsType(t.types, missingType); }) ? missingType : undefinedType; removeFromEach(typeSet, 32768 /* TypeFlags.Undefined */); result = getUnionType([getIntersectionType(typeSet), undefinedOrMissingType], 1 /* UnionReduction.Literal */, aliasSymbol, aliasTypeArguments); } - else if (eachIsUnionContaining(typeSet, 65536 /* TypeFlags.Null */)) { + else if (ts.every(typeSet, function (t) { return !!(t.flags & 1048576 /* TypeFlags.Union */ && (t.types[0].flags & 65536 /* TypeFlags.Null */ || t.types[1].flags & 65536 /* TypeFlags.Null */)); })) { removeFromEach(typeSet, 65536 /* TypeFlags.Null */); result = getUnionType([getIntersectionType(typeSet), nullType], 1 /* UnionReduction.Literal */, aliasSymbol, aliasTypeArguments); } @@ -69592,6 +69621,20 @@ var ts; if (containsType(targetTypes, source)) { return -1 /* Ternary.True */; } + if (ts.getObjectFlags(target) & 32768 /* ObjectFlags.PrimitiveUnion */ && !(source.flags & 1024 /* TypeFlags.EnumLiteral */) && (source.flags & (128 /* TypeFlags.StringLiteral */ | 512 /* TypeFlags.BooleanLiteral */ | 2048 /* TypeFlags.BigIntLiteral */) || + (relation === subtypeRelation || relation === strictSubtypeRelation) && source.flags & 256 /* TypeFlags.NumberLiteral */)) { + // When relating a literal type to a union of primitive types, we know the relation is false unless + // the union contains the base primitive type or the literal type in one of its fresh/regular forms. + // We exclude numeric literals for non-subtype relations because numeric literals are assignable to + // numeric enum literals with the same value. Similarly, we exclude enum literal types because + // identically named enum types are related (see isEmumTypeRelatedTo). + var alternateForm = source === source.regularType ? source.freshType : source.regularType; + var primitive = source.flags & 128 /* TypeFlags.StringLiteral */ ? stringType : + source.flags & 256 /* TypeFlags.NumberLiteral */ ? numberType : + source.flags & 2048 /* TypeFlags.BigIntLiteral */ ? bigintType : + undefined; + return primitive && containsType(targetTypes, primitive) || alternateForm && containsType(targetTypes, alternateForm) ? -1 /* Ternary.True */ : 0 /* Ternary.False */; + } var match = getMatchingUnionConstituentForType(target, source); if (match) { var related = isRelatedTo(source, match, 2 /* RecursionFlags.Target */, /*reportErrors*/ false); @@ -117562,6 +117605,14 @@ var ts; PipelinePhase[PipelinePhase["SourceMaps"] = 3] = "SourceMaps"; PipelinePhase[PipelinePhase["Emit"] = 4] = "Emit"; })(PipelinePhase || (PipelinePhase = {})); + /** @internal */ + ts.createPrinterWithDefaults = ts.memoize(function () { return createPrinter({}); }); + /** @internal */ + ts.createPrinterWithRemoveComments = ts.memoize(function () { return createPrinter({ removeComments: true }); }); + /** @internal */ + ts.createPrinterWithRemoveCommentsNeverAsciiEscape = ts.memoize(function () { return createPrinter({ removeComments: true, neverAsciiEscape: true }); }); + /** @internal */ + ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon = ts.memoize(function () { return createPrinter({ removeComments: true, omitTrailingSemicolon: true }); }); function createPrinter(printerOptions, handlers) { if (printerOptions === void 0) { printerOptions = {}; } if (handlers === void 0) { handlers = {}; } @@ -136370,7 +136421,7 @@ var ts; function nodeToDisplayParts(node, enclosingDeclaration) { var file = enclosingDeclaration.getSourceFile(); return mapToDisplayParts(function (writer) { - var printer = ts.createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + var printer = ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon(); printer.writeNode(4 /* EmitHint.Unspecified */, node, file, writer); }); } @@ -147099,7 +147150,7 @@ var ts; } if (text === undefined) { // get the text from printing the node on a single line without comments... - var printer_1 = ts.createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + var printer_1 = ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon(); text = ts.usingSingleLineStringWriter(function (writer) { return printer_1.writeNode(4 /* EmitHint.Unspecified */, node, node.getSourceFile(), writer); }); } return { text: text, pos: declName.getStart(), end: declName.getEnd() }; @@ -152368,7 +152419,7 @@ var ts; } function getTypeHelpItem(symbol, typeParameters, checker, enclosingDeclaration, sourceFile) { var typeSymbolDisplay = ts.symbolToDisplayParts(checker, symbol); - var printer = ts.createPrinter({ removeComments: true }); + var printer = ts.createPrinterWithRemoveComments(); var parameters = typeParameters.map(function (t) { return createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer); }); var documentation = symbol.getDocumentationComment(checker); var tags = symbol.getJsDocTags(checker); @@ -152402,7 +152453,7 @@ var ts; } function itemInfoForTypeParameters(candidateSignature, checker, enclosingDeclaration, sourceFile) { var typeParameters = (candidateSignature.target || candidateSignature).typeParameters; - var printer = ts.createPrinter({ removeComments: true }); + var printer = ts.createPrinterWithRemoveComments(); var parameters = (typeParameters || ts.emptyArray).map(function (t) { return createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer); }); var thisParameter = candidateSignature.thisParameter ? [checker.symbolToParameterDeclaration(candidateSignature.thisParameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)] : []; return checker.getExpandedParameters(candidateSignature).map(function (paramList) { @@ -152414,7 +152465,7 @@ var ts; }); } function itemInfoForParameters(candidateSignature, checker, enclosingDeclaration, sourceFile) { - var printer = ts.createPrinter({ removeComments: true }); + var printer = ts.createPrinterWithRemoveComments(); var typeParameterParts = ts.mapToDisplayParts(function (writer) { if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) { var args = ts.factory.createNodeArray(candidateSignature.typeParameters.map(function (p) { return checker.typeParameterToDeclaration(p, enclosingDeclaration, signatureHelpNodeBuilderFlags); })); @@ -152717,8 +152768,7 @@ var ts; } function printTypeInSingleLine(type) { var flags = 70221824 /* NodeBuilderFlags.IgnoreErrors */ | 1048576 /* TypeFormatFlags.AllowUniqueESSymbolType */ | 16384 /* TypeFormatFlags.UseAliasDefinedOutsideCurrentScope */; - var options = { removeComments: true }; - var printer = ts.createPrinter(options); + var printer = ts.createPrinterWithRemoveComments(); return ts.usingSingleLineStringWriter(function (writer) { var typeNode = checker.typeToTypeNode(type, /*enclosingDeclaration*/ undefined, flags, writer); ts.Debug.assertIsDefined(typeNode, "should always get typenode"); @@ -153263,7 +153313,6 @@ var ts; var hasAddedSymbolInfo = false; var isThisExpression = location.kind === 109 /* SyntaxKind.ThisKeyword */ && ts.isInExpressionContext(location) || ts.isThisInTypeQuery(location); var type; - var printer; var documentationFromAlias; var tagsFromAlias; var hasMultipleSignatures = false; @@ -153706,10 +153755,7 @@ var ts; } return { displayParts: displayParts, documentation: documentation, symbolKind: symbolKind, tags: tags.length === 0 ? undefined : tags }; function getPrinter() { - if (!printer) { - printer = ts.createPrinter({ removeComments: true }); - } - return printer; + return ts.createPrinterWithRemoveComments(); } function prefixNextMeaning() { if (displayParts.length) { diff --git a/lib/tsserverlibrary.js b/lib/tsserverlibrary.js index 65d0e784d1..0332d8e54b 100644 --- a/lib/tsserverlibrary.js +++ b/lib/tsserverlibrary.js @@ -5429,7 +5429,7 @@ var ts; /* @internal */ TypeFlags[TypeFlags["IncludesInstantiable"] = 33554432] = "IncludesInstantiable"; /* @internal */ - TypeFlags[TypeFlags["NotPrimitiveUnion"] = 36323363] = "NotPrimitiveUnion"; + TypeFlags[TypeFlags["NotPrimitiveUnion"] = 36323331] = "NotPrimitiveUnion"; })(TypeFlags = ts.TypeFlags || (ts.TypeFlags = {})); // Types included in TypeFlags.ObjectFlagsType have an objectFlags property. Some ObjectFlags // are specific to certain types and reuse the same bit position. Those ObjectFlags require a check @@ -39322,7 +39322,7 @@ var ts; return withJSDoc(finishNode(node, pos), hasJSDoc); } function isSetLazy(identifier) { - // 1. import lazy { export } from "mod"; + // 1. import lazy { export } from "mod"; // 2. import lazy defaultExport from "mod"; // 3. import lazy defaultExport, { export, /* ... */ } from "mod"; return (identifier === null || identifier === void 0 ? void 0 : identifier.escapedText) === 'lazy' && @@ -48426,6 +48426,7 @@ var ts; var preSwitchCaseFlow; var activeLabelList; var hasExplicitReturn; + var hasFlowEffects; // state used for emit helpers var emitFlags; // If this file is an external module, then it is automatically in strict-mode according to @@ -48489,6 +48490,7 @@ var ts; currentExceptionTarget = undefined; activeLabelList = undefined; hasExplicitReturn = false; + hasFlowEffects = false; inAssignmentPattern = false; emitFlags = 0 /* NodeFlags.None */; } @@ -49049,8 +49051,8 @@ var ts; function isNarrowingExpression(expr) { switch (expr.kind) { case 79 /* SyntaxKind.Identifier */: - case 80 /* SyntaxKind.PrivateIdentifier */: case 109 /* SyntaxKind.ThisKeyword */: + return true; case 211 /* SyntaxKind.PropertyAccessExpression */: case 212 /* SyntaxKind.ElementAccessExpression */: return containsNarrowableReference(expr); @@ -49069,11 +49071,24 @@ var ts; return false; } function isNarrowableReference(expr) { - return ts.isDottedName(expr) - || (ts.isPropertyAccessExpression(expr) || ts.isNonNullExpression(expr) || ts.isParenthesizedExpression(expr)) && isNarrowableReference(expr.expression) - || ts.isBinaryExpression(expr) && expr.operatorToken.kind === 27 /* SyntaxKind.CommaToken */ && isNarrowableReference(expr.right) - || ts.isElementAccessExpression(expr) && (ts.isStringOrNumericLiteralLike(expr.argumentExpression) || ts.isEntityNameExpression(expr.argumentExpression)) && isNarrowableReference(expr.expression) - || ts.isAssignmentExpression(expr) && isNarrowableReference(expr.left); + switch (expr.kind) { + case 79 /* SyntaxKind.Identifier */: + case 109 /* SyntaxKind.ThisKeyword */: + case 107 /* SyntaxKind.SuperKeyword */: + case 237 /* SyntaxKind.MetaProperty */: + return true; + case 211 /* SyntaxKind.PropertyAccessExpression */: + case 217 /* SyntaxKind.ParenthesizedExpression */: + case 236 /* SyntaxKind.NonNullExpression */: + return isNarrowableReference(expr.expression); + case 212 /* SyntaxKind.ElementAccessExpression */: + return (ts.isStringOrNumericLiteralLike(expr.argumentExpression) || ts.isEntityNameExpression(expr.argumentExpression)) && + isNarrowableReference(expr.expression); + case 227 /* SyntaxKind.BinaryExpression */: + return expr.operatorToken.kind === 27 /* SyntaxKind.CommaToken */ && isNarrowableReference(expr.right) || + ts.isAssignmentOperator(expr.operatorToken.kind) && ts.isLeftHandSideExpression(expr.left); + } + return false; } function containsNarrowableReference(expr) { return isNarrowableReference(expr) || ts.isOptionalChain(expr) && containsNarrowableReference(expr.expression); @@ -49175,6 +49190,7 @@ var ts; } function createFlowMutation(flags, antecedent, node) { setFlowNodeReferenced(antecedent); + hasFlowEffects = true; var result = initFlowNode({ flags: flags, antecedent: antecedent, node: node }); if (currentExceptionTarget) { addAntecedent(currentExceptionTarget, result); @@ -49183,6 +49199,7 @@ var ts; } function createFlowCall(antecedent, node) { setFlowNodeReferenced(antecedent); + hasFlowEffects = true; return initFlowNode({ flags: 512 /* FlowFlags.Call */, antecedent: antecedent, node: node }); } function finishFlowLabel(flow) { @@ -49348,6 +49365,7 @@ var ts; } } currentFlow = unreachableFlow; + hasFlowEffects = true; } function findActiveLabel(name) { for (var label = activeLabelList; label; label = label.next) { @@ -49362,6 +49380,7 @@ var ts; if (flowLabel) { addAntecedent(flowLabel, currentFlow); currentFlow = unreachableFlow; + hasFlowEffects = true; } } function bindBreakOrContinueStatement(node) { @@ -49667,8 +49686,12 @@ var ts; ts.isLogicalOrCoalescingAssignmentOperator(operator)) { if (isTopLevelLogicalExpression(node)) { var postExpressionLabel = createBranchLabel(); + var saveCurrentFlow = currentFlow; + var saveHasFlowEffects = hasFlowEffects; + hasFlowEffects = false; bindLogicalLikeExpression(node, postExpressionLabel, postExpressionLabel); - currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects || (hasFlowEffects = saveHasFlowEffects); } else { bindLogicalLikeExpression(node, currentTrueTarget, currentFalseTarget); @@ -49741,6 +49764,9 @@ var ts; var trueLabel = createBranchLabel(); var falseLabel = createBranchLabel(); var postExpressionLabel = createBranchLabel(); + var saveCurrentFlow = currentFlow; + var saveHasFlowEffects = hasFlowEffects; + hasFlowEffects = false; bindCondition(node.condition, trueLabel, falseLabel); currentFlow = finishFlowLabel(trueLabel); bind(node.questionToken); @@ -49751,6 +49777,8 @@ var ts; bind(node.whenFalse); addAntecedent(postExpressionLabel, currentFlow); currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects || (hasFlowEffects = saveHasFlowEffects); } function bindInitializedVariableFlow(node) { var name = !ts.isOmittedExpression(node) ? node.name : undefined; @@ -49872,8 +49900,11 @@ var ts; function bindOptionalChainFlow(node) { if (isTopLevelLogicalExpression(node)) { var postExpressionLabel = createBranchLabel(); + var saveCurrentFlow = currentFlow; + var saveHasFlowEffects = hasFlowEffects; bindOptionalChain(node, postExpressionLabel, postExpressionLabel); - currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects || (hasFlowEffects = saveHasFlowEffects); } else { bindOptionalChain(node, currentTrueTarget, currentFalseTarget); @@ -56277,7 +56308,9 @@ var ts; function symbolToStringWorker(writer) { var entity = builder(symbol, meaning, enclosingDeclaration, nodeFlags); // TODO: GH#18217 // add neverAsciiEscape for GH#39027 - var printer = (enclosingDeclaration === null || enclosingDeclaration === void 0 ? void 0 : enclosingDeclaration.kind) === 314 /* SyntaxKind.SourceFile */ ? ts.createPrinter({ removeComments: true, neverAsciiEscape: true }) : ts.createPrinter({ removeComments: true }); + var printer = (enclosingDeclaration === null || enclosingDeclaration === void 0 ? void 0 : enclosingDeclaration.kind) === 314 /* SyntaxKind.SourceFile */ + ? ts.createPrinterWithRemoveCommentsNeverAsciiEscape() + : ts.createPrinterWithRemoveComments(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, entity, /*sourceFile*/ sourceFile, writer); return writer; @@ -56295,7 +56328,7 @@ var ts; sigOutput = kind === 1 /* SignatureKind.Construct */ ? 180 /* SyntaxKind.ConstructSignature */ : 179 /* SyntaxKind.CallSignature */; } var sig = nodeBuilder.signatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, toNodeBuilderFlags(flags) | 70221824 /* NodeBuilderFlags.IgnoreErrors */ | 512 /* NodeBuilderFlags.WriteTypeParametersInQualifiedName */); - var printer = ts.createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + var printer = ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, sig, /*sourceFile*/ sourceFile, ts.getTrailingSemicolonDeferringWriter(writer)); // TODO: GH#18217 return writer; @@ -56310,8 +56343,7 @@ var ts; return ts.Debug.fail("should always get typenode"); // The unresolved type gets a synthesized comment on `any` to hint to users that it's not a plain `any`. // Otherwise, we always strip comments out. - var options = { removeComments: type !== unresolvedType }; - var printer = ts.createPrinter(options); + var printer = type !== unresolvedType ? ts.createPrinterWithRemoveComments() : ts.createPrinterWithDefaults(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, typeNode, /*sourceFile*/ sourceFile, writer); var result = writer.getText(); @@ -59387,7 +59419,7 @@ var ts; function typePredicateToStringWorker(writer) { var predicate = ts.factory.createTypePredicateNode(typePredicate.kind === 2 /* TypePredicateKind.AssertsThis */ || typePredicate.kind === 3 /* TypePredicateKind.AssertsIdentifier */ ? ts.factory.createToken(130 /* SyntaxKind.AssertsKeyword */) : undefined, typePredicate.kind === 1 /* TypePredicateKind.Identifier */ || typePredicate.kind === 3 /* TypePredicateKind.AssertsIdentifier */ ? ts.factory.createIdentifier(typePredicate.parameterName) : ts.factory.createThisTypeNode(), typePredicate.type && nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | 70221824 /* NodeBuilderFlags.IgnoreErrors */ | 512 /* NodeBuilderFlags.WriteTypeParametersInQualifiedName */) // TODO: GH#18217 ); - var printer = ts.createPrinter({ removeComments: true }); + var printer = ts.createPrinterWithRemoveComments(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, predicate, /*sourceFile*/ sourceFile, writer); return writer; @@ -65520,7 +65552,7 @@ var ts; origin = createOriginUnionOrIntersectionType(1048576 /* TypeFlags.Union */, reducedTypes); } } - var objectFlags = (includes & 36323363 /* TypeFlags.NotPrimitiveUnion */ ? 0 : 32768 /* ObjectFlags.PrimitiveUnion */) | + var objectFlags = (includes & 36323331 /* TypeFlags.NotPrimitiveUnion */ ? 0 : 32768 /* ObjectFlags.PrimitiveUnion */) | (includes & 2097152 /* TypeFlags.Intersection */ ? 16777216 /* ObjectFlags.ContainsIntersections */ : 0); return getUnionTypeFromSortedList(typeSet, objectFlags, aliasSymbol, aliasTypeArguments, origin); } @@ -65663,7 +65695,7 @@ var ts; var u = unionTypes_1[_i]; if (!containsType(u.types, type)) { var primitive = type.flags & 128 /* TypeFlags.StringLiteral */ ? stringType : - type.flags & 256 /* TypeFlags.NumberLiteral */ ? numberType : + type.flags & (32 /* TypeFlags.Enum */ | 256 /* TypeFlags.NumberLiteral */) ? numberType : type.flags & 2048 /* TypeFlags.BigIntLiteral */ ? bigintType : type.flags & 8192 /* TypeFlags.UniqueESSymbol */ ? esSymbolType : undefined; @@ -65699,9 +65731,6 @@ var ts; } return false; } - function eachIsUnionContaining(types, flag) { - return ts.every(types, function (t) { return !!(t.flags & 1048576 /* TypeFlags.Union */) && ts.some(t.types, function (tt) { return !!(tt.flags & flag); }); }); - } function removeFromEach(types, flag) { for (var i = 0; i < types.length; i++) { types[i] = filterType(types[i], function (t) { return !(t.flags & flag); }); @@ -65833,12 +65862,12 @@ var ts; // reduced we'll never reduce again, so this occurs at most once. result = getIntersectionType(typeSet, aliasSymbol, aliasTypeArguments); } - else if (eachIsUnionContaining(typeSet, 32768 /* TypeFlags.Undefined */)) { + else if (ts.every(typeSet, function (t) { return !!(t.flags & 1048576 /* TypeFlags.Union */ && t.types[0].flags & 32768 /* TypeFlags.Undefined */); })) { var undefinedOrMissingType = exactOptionalPropertyTypes && ts.some(typeSet, function (t) { return containsType(t.types, missingType); }) ? missingType : undefinedType; removeFromEach(typeSet, 32768 /* TypeFlags.Undefined */); result = getUnionType([getIntersectionType(typeSet), undefinedOrMissingType], 1 /* UnionReduction.Literal */, aliasSymbol, aliasTypeArguments); } - else if (eachIsUnionContaining(typeSet, 65536 /* TypeFlags.Null */)) { + else if (ts.every(typeSet, function (t) { return !!(t.flags & 1048576 /* TypeFlags.Union */ && (t.types[0].flags & 65536 /* TypeFlags.Null */ || t.types[1].flags & 65536 /* TypeFlags.Null */)); })) { removeFromEach(typeSet, 65536 /* TypeFlags.Null */); result = getUnionType([getIntersectionType(typeSet), nullType], 1 /* UnionReduction.Literal */, aliasSymbol, aliasTypeArguments); } @@ -69591,6 +69620,20 @@ var ts; if (containsType(targetTypes, source)) { return -1 /* Ternary.True */; } + if (ts.getObjectFlags(target) & 32768 /* ObjectFlags.PrimitiveUnion */ && !(source.flags & 1024 /* TypeFlags.EnumLiteral */) && (source.flags & (128 /* TypeFlags.StringLiteral */ | 512 /* TypeFlags.BooleanLiteral */ | 2048 /* TypeFlags.BigIntLiteral */) || + (relation === subtypeRelation || relation === strictSubtypeRelation) && source.flags & 256 /* TypeFlags.NumberLiteral */)) { + // When relating a literal type to a union of primitive types, we know the relation is false unless + // the union contains the base primitive type or the literal type in one of its fresh/regular forms. + // We exclude numeric literals for non-subtype relations because numeric literals are assignable to + // numeric enum literals with the same value. Similarly, we exclude enum literal types because + // identically named enum types are related (see isEmumTypeRelatedTo). + var alternateForm = source === source.regularType ? source.freshType : source.regularType; + var primitive = source.flags & 128 /* TypeFlags.StringLiteral */ ? stringType : + source.flags & 256 /* TypeFlags.NumberLiteral */ ? numberType : + source.flags & 2048 /* TypeFlags.BigIntLiteral */ ? bigintType : + undefined; + return primitive && containsType(targetTypes, primitive) || alternateForm && containsType(targetTypes, alternateForm) ? -1 /* Ternary.True */ : 0 /* Ternary.False */; + } var match = getMatchingUnionConstituentForType(target, source); if (match) { var related = isRelatedTo(source, match, 2 /* RecursionFlags.Target */, /*reportErrors*/ false); @@ -117561,6 +117604,14 @@ var ts; PipelinePhase[PipelinePhase["SourceMaps"] = 3] = "SourceMaps"; PipelinePhase[PipelinePhase["Emit"] = 4] = "Emit"; })(PipelinePhase || (PipelinePhase = {})); + /** @internal */ + ts.createPrinterWithDefaults = ts.memoize(function () { return createPrinter({}); }); + /** @internal */ + ts.createPrinterWithRemoveComments = ts.memoize(function () { return createPrinter({ removeComments: true }); }); + /** @internal */ + ts.createPrinterWithRemoveCommentsNeverAsciiEscape = ts.memoize(function () { return createPrinter({ removeComments: true, neverAsciiEscape: true }); }); + /** @internal */ + ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon = ts.memoize(function () { return createPrinter({ removeComments: true, omitTrailingSemicolon: true }); }); function createPrinter(printerOptions, handlers) { if (printerOptions === void 0) { printerOptions = {}; } if (handlers === void 0) { handlers = {}; } @@ -136789,7 +136840,7 @@ var ts; function nodeToDisplayParts(node, enclosingDeclaration) { var file = enclosingDeclaration.getSourceFile(); return mapToDisplayParts(function (writer) { - var printer = ts.createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + var printer = ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon(); printer.writeNode(4 /* EmitHint.Unspecified */, node, file, writer); }); } @@ -147518,7 +147569,7 @@ var ts; } if (text === undefined) { // get the text from printing the node on a single line without comments... - var printer_1 = ts.createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + var printer_1 = ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon(); text = ts.usingSingleLineStringWriter(function (writer) { return printer_1.writeNode(4 /* EmitHint.Unspecified */, node, node.getSourceFile(), writer); }); } return { text: text, pos: declName.getStart(), end: declName.getEnd() }; @@ -152787,7 +152838,7 @@ var ts; } function getTypeHelpItem(symbol, typeParameters, checker, enclosingDeclaration, sourceFile) { var typeSymbolDisplay = ts.symbolToDisplayParts(checker, symbol); - var printer = ts.createPrinter({ removeComments: true }); + var printer = ts.createPrinterWithRemoveComments(); var parameters = typeParameters.map(function (t) { return createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer); }); var documentation = symbol.getDocumentationComment(checker); var tags = symbol.getJsDocTags(checker); @@ -152821,7 +152872,7 @@ var ts; } function itemInfoForTypeParameters(candidateSignature, checker, enclosingDeclaration, sourceFile) { var typeParameters = (candidateSignature.target || candidateSignature).typeParameters; - var printer = ts.createPrinter({ removeComments: true }); + var printer = ts.createPrinterWithRemoveComments(); var parameters = (typeParameters || ts.emptyArray).map(function (t) { return createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer); }); var thisParameter = candidateSignature.thisParameter ? [checker.symbolToParameterDeclaration(candidateSignature.thisParameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)] : []; return checker.getExpandedParameters(candidateSignature).map(function (paramList) { @@ -152833,7 +152884,7 @@ var ts; }); } function itemInfoForParameters(candidateSignature, checker, enclosingDeclaration, sourceFile) { - var printer = ts.createPrinter({ removeComments: true }); + var printer = ts.createPrinterWithRemoveComments(); var typeParameterParts = ts.mapToDisplayParts(function (writer) { if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) { var args = ts.factory.createNodeArray(candidateSignature.typeParameters.map(function (p) { return checker.typeParameterToDeclaration(p, enclosingDeclaration, signatureHelpNodeBuilderFlags); })); @@ -153136,8 +153187,7 @@ var ts; } function printTypeInSingleLine(type) { var flags = 70221824 /* NodeBuilderFlags.IgnoreErrors */ | 1048576 /* TypeFormatFlags.AllowUniqueESSymbolType */ | 16384 /* TypeFormatFlags.UseAliasDefinedOutsideCurrentScope */; - var options = { removeComments: true }; - var printer = ts.createPrinter(options); + var printer = ts.createPrinterWithRemoveComments(); return ts.usingSingleLineStringWriter(function (writer) { var typeNode = checker.typeToTypeNode(type, /*enclosingDeclaration*/ undefined, flags, writer); ts.Debug.assertIsDefined(typeNode, "should always get typenode"); @@ -153682,7 +153732,6 @@ var ts; var hasAddedSymbolInfo = false; var isThisExpression = location.kind === 109 /* SyntaxKind.ThisKeyword */ && ts.isInExpressionContext(location) || ts.isThisInTypeQuery(location); var type; - var printer; var documentationFromAlias; var tagsFromAlias; var hasMultipleSignatures = false; @@ -154125,10 +154174,7 @@ var ts; } return { displayParts: displayParts, documentation: documentation, symbolKind: symbolKind, tags: tags.length === 0 ? undefined : tags }; function getPrinter() { - if (!printer) { - printer = ts.createPrinter({ removeComments: true }); - } - return printer; + return ts.createPrinterWithRemoveComments(); } function prefixNextMeaning() { if (displayParts.length) { diff --git a/lib/typescript.js b/lib/typescript.js index 3b0785a504..50407ad485 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -5420,7 +5420,7 @@ var ts; /* @internal */ TypeFlags[TypeFlags["IncludesInstantiable"] = 33554432] = "IncludesInstantiable"; /* @internal */ - TypeFlags[TypeFlags["NotPrimitiveUnion"] = 36323363] = "NotPrimitiveUnion"; + TypeFlags[TypeFlags["NotPrimitiveUnion"] = 36323331] = "NotPrimitiveUnion"; })(TypeFlags = ts.TypeFlags || (ts.TypeFlags = {})); // Types included in TypeFlags.ObjectFlagsType have an objectFlags property. Some ObjectFlags // are specific to certain types and reuse the same bit position. Those ObjectFlags require a check @@ -39313,7 +39313,7 @@ var ts; return withJSDoc(finishNode(node, pos), hasJSDoc); } function isSetLazy(identifier) { - // 1. import lazy { export } from "mod"; + // 1. import lazy { export } from "mod"; // 2. import lazy defaultExport from "mod"; // 3. import lazy defaultExport, { export, /* ... */ } from "mod"; return (identifier === null || identifier === void 0 ? void 0 : identifier.escapedText) === 'lazy' && @@ -48417,6 +48417,7 @@ var ts; var preSwitchCaseFlow; var activeLabelList; var hasExplicitReturn; + var hasFlowEffects; // state used for emit helpers var emitFlags; // If this file is an external module, then it is automatically in strict-mode according to @@ -48480,6 +48481,7 @@ var ts; currentExceptionTarget = undefined; activeLabelList = undefined; hasExplicitReturn = false; + hasFlowEffects = false; inAssignmentPattern = false; emitFlags = 0 /* NodeFlags.None */; } @@ -49040,8 +49042,8 @@ var ts; function isNarrowingExpression(expr) { switch (expr.kind) { case 79 /* SyntaxKind.Identifier */: - case 80 /* SyntaxKind.PrivateIdentifier */: case 109 /* SyntaxKind.ThisKeyword */: + return true; case 211 /* SyntaxKind.PropertyAccessExpression */: case 212 /* SyntaxKind.ElementAccessExpression */: return containsNarrowableReference(expr); @@ -49060,11 +49062,24 @@ var ts; return false; } function isNarrowableReference(expr) { - return ts.isDottedName(expr) - || (ts.isPropertyAccessExpression(expr) || ts.isNonNullExpression(expr) || ts.isParenthesizedExpression(expr)) && isNarrowableReference(expr.expression) - || ts.isBinaryExpression(expr) && expr.operatorToken.kind === 27 /* SyntaxKind.CommaToken */ && isNarrowableReference(expr.right) - || ts.isElementAccessExpression(expr) && (ts.isStringOrNumericLiteralLike(expr.argumentExpression) || ts.isEntityNameExpression(expr.argumentExpression)) && isNarrowableReference(expr.expression) - || ts.isAssignmentExpression(expr) && isNarrowableReference(expr.left); + switch (expr.kind) { + case 79 /* SyntaxKind.Identifier */: + case 109 /* SyntaxKind.ThisKeyword */: + case 107 /* SyntaxKind.SuperKeyword */: + case 237 /* SyntaxKind.MetaProperty */: + return true; + case 211 /* SyntaxKind.PropertyAccessExpression */: + case 217 /* SyntaxKind.ParenthesizedExpression */: + case 236 /* SyntaxKind.NonNullExpression */: + return isNarrowableReference(expr.expression); + case 212 /* SyntaxKind.ElementAccessExpression */: + return (ts.isStringOrNumericLiteralLike(expr.argumentExpression) || ts.isEntityNameExpression(expr.argumentExpression)) && + isNarrowableReference(expr.expression); + case 227 /* SyntaxKind.BinaryExpression */: + return expr.operatorToken.kind === 27 /* SyntaxKind.CommaToken */ && isNarrowableReference(expr.right) || + ts.isAssignmentOperator(expr.operatorToken.kind) && ts.isLeftHandSideExpression(expr.left); + } + return false; } function containsNarrowableReference(expr) { return isNarrowableReference(expr) || ts.isOptionalChain(expr) && containsNarrowableReference(expr.expression); @@ -49166,6 +49181,7 @@ var ts; } function createFlowMutation(flags, antecedent, node) { setFlowNodeReferenced(antecedent); + hasFlowEffects = true; var result = initFlowNode({ flags: flags, antecedent: antecedent, node: node }); if (currentExceptionTarget) { addAntecedent(currentExceptionTarget, result); @@ -49174,6 +49190,7 @@ var ts; } function createFlowCall(antecedent, node) { setFlowNodeReferenced(antecedent); + hasFlowEffects = true; return initFlowNode({ flags: 512 /* FlowFlags.Call */, antecedent: antecedent, node: node }); } function finishFlowLabel(flow) { @@ -49339,6 +49356,7 @@ var ts; } } currentFlow = unreachableFlow; + hasFlowEffects = true; } function findActiveLabel(name) { for (var label = activeLabelList; label; label = label.next) { @@ -49353,6 +49371,7 @@ var ts; if (flowLabel) { addAntecedent(flowLabel, currentFlow); currentFlow = unreachableFlow; + hasFlowEffects = true; } } function bindBreakOrContinueStatement(node) { @@ -49658,8 +49677,12 @@ var ts; ts.isLogicalOrCoalescingAssignmentOperator(operator)) { if (isTopLevelLogicalExpression(node)) { var postExpressionLabel = createBranchLabel(); + var saveCurrentFlow = currentFlow; + var saveHasFlowEffects = hasFlowEffects; + hasFlowEffects = false; bindLogicalLikeExpression(node, postExpressionLabel, postExpressionLabel); - currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects || (hasFlowEffects = saveHasFlowEffects); } else { bindLogicalLikeExpression(node, currentTrueTarget, currentFalseTarget); @@ -49732,6 +49755,9 @@ var ts; var trueLabel = createBranchLabel(); var falseLabel = createBranchLabel(); var postExpressionLabel = createBranchLabel(); + var saveCurrentFlow = currentFlow; + var saveHasFlowEffects = hasFlowEffects; + hasFlowEffects = false; bindCondition(node.condition, trueLabel, falseLabel); currentFlow = finishFlowLabel(trueLabel); bind(node.questionToken); @@ -49742,6 +49768,8 @@ var ts; bind(node.whenFalse); addAntecedent(postExpressionLabel, currentFlow); currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects || (hasFlowEffects = saveHasFlowEffects); } function bindInitializedVariableFlow(node) { var name = !ts.isOmittedExpression(node) ? node.name : undefined; @@ -49863,8 +49891,11 @@ var ts; function bindOptionalChainFlow(node) { if (isTopLevelLogicalExpression(node)) { var postExpressionLabel = createBranchLabel(); + var saveCurrentFlow = currentFlow; + var saveHasFlowEffects = hasFlowEffects; bindOptionalChain(node, postExpressionLabel, postExpressionLabel); - currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects || (hasFlowEffects = saveHasFlowEffects); } else { bindOptionalChain(node, currentTrueTarget, currentFalseTarget); @@ -56268,7 +56299,9 @@ var ts; function symbolToStringWorker(writer) { var entity = builder(symbol, meaning, enclosingDeclaration, nodeFlags); // TODO: GH#18217 // add neverAsciiEscape for GH#39027 - var printer = (enclosingDeclaration === null || enclosingDeclaration === void 0 ? void 0 : enclosingDeclaration.kind) === 314 /* SyntaxKind.SourceFile */ ? ts.createPrinter({ removeComments: true, neverAsciiEscape: true }) : ts.createPrinter({ removeComments: true }); + var printer = (enclosingDeclaration === null || enclosingDeclaration === void 0 ? void 0 : enclosingDeclaration.kind) === 314 /* SyntaxKind.SourceFile */ + ? ts.createPrinterWithRemoveCommentsNeverAsciiEscape() + : ts.createPrinterWithRemoveComments(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, entity, /*sourceFile*/ sourceFile, writer); return writer; @@ -56286,7 +56319,7 @@ var ts; sigOutput = kind === 1 /* SignatureKind.Construct */ ? 180 /* SyntaxKind.ConstructSignature */ : 179 /* SyntaxKind.CallSignature */; } var sig = nodeBuilder.signatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, toNodeBuilderFlags(flags) | 70221824 /* NodeBuilderFlags.IgnoreErrors */ | 512 /* NodeBuilderFlags.WriteTypeParametersInQualifiedName */); - var printer = ts.createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + var printer = ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, sig, /*sourceFile*/ sourceFile, ts.getTrailingSemicolonDeferringWriter(writer)); // TODO: GH#18217 return writer; @@ -56301,8 +56334,7 @@ var ts; return ts.Debug.fail("should always get typenode"); // The unresolved type gets a synthesized comment on `any` to hint to users that it's not a plain `any`. // Otherwise, we always strip comments out. - var options = { removeComments: type !== unresolvedType }; - var printer = ts.createPrinter(options); + var printer = type !== unresolvedType ? ts.createPrinterWithRemoveComments() : ts.createPrinterWithDefaults(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, typeNode, /*sourceFile*/ sourceFile, writer); var result = writer.getText(); @@ -59378,7 +59410,7 @@ var ts; function typePredicateToStringWorker(writer) { var predicate = ts.factory.createTypePredicateNode(typePredicate.kind === 2 /* TypePredicateKind.AssertsThis */ || typePredicate.kind === 3 /* TypePredicateKind.AssertsIdentifier */ ? ts.factory.createToken(130 /* SyntaxKind.AssertsKeyword */) : undefined, typePredicate.kind === 1 /* TypePredicateKind.Identifier */ || typePredicate.kind === 3 /* TypePredicateKind.AssertsIdentifier */ ? ts.factory.createIdentifier(typePredicate.parameterName) : ts.factory.createThisTypeNode(), typePredicate.type && nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | 70221824 /* NodeBuilderFlags.IgnoreErrors */ | 512 /* NodeBuilderFlags.WriteTypeParametersInQualifiedName */) // TODO: GH#18217 ); - var printer = ts.createPrinter({ removeComments: true }); + var printer = ts.createPrinterWithRemoveComments(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, predicate, /*sourceFile*/ sourceFile, writer); return writer; @@ -65511,7 +65543,7 @@ var ts; origin = createOriginUnionOrIntersectionType(1048576 /* TypeFlags.Union */, reducedTypes); } } - var objectFlags = (includes & 36323363 /* TypeFlags.NotPrimitiveUnion */ ? 0 : 32768 /* ObjectFlags.PrimitiveUnion */) | + var objectFlags = (includes & 36323331 /* TypeFlags.NotPrimitiveUnion */ ? 0 : 32768 /* ObjectFlags.PrimitiveUnion */) | (includes & 2097152 /* TypeFlags.Intersection */ ? 16777216 /* ObjectFlags.ContainsIntersections */ : 0); return getUnionTypeFromSortedList(typeSet, objectFlags, aliasSymbol, aliasTypeArguments, origin); } @@ -65654,7 +65686,7 @@ var ts; var u = unionTypes_1[_i]; if (!containsType(u.types, type)) { var primitive = type.flags & 128 /* TypeFlags.StringLiteral */ ? stringType : - type.flags & 256 /* TypeFlags.NumberLiteral */ ? numberType : + type.flags & (32 /* TypeFlags.Enum */ | 256 /* TypeFlags.NumberLiteral */) ? numberType : type.flags & 2048 /* TypeFlags.BigIntLiteral */ ? bigintType : type.flags & 8192 /* TypeFlags.UniqueESSymbol */ ? esSymbolType : undefined; @@ -65690,9 +65722,6 @@ var ts; } return false; } - function eachIsUnionContaining(types, flag) { - return ts.every(types, function (t) { return !!(t.flags & 1048576 /* TypeFlags.Union */) && ts.some(t.types, function (tt) { return !!(tt.flags & flag); }); }); - } function removeFromEach(types, flag) { for (var i = 0; i < types.length; i++) { types[i] = filterType(types[i], function (t) { return !(t.flags & flag); }); @@ -65824,12 +65853,12 @@ var ts; // reduced we'll never reduce again, so this occurs at most once. result = getIntersectionType(typeSet, aliasSymbol, aliasTypeArguments); } - else if (eachIsUnionContaining(typeSet, 32768 /* TypeFlags.Undefined */)) { + else if (ts.every(typeSet, function (t) { return !!(t.flags & 1048576 /* TypeFlags.Union */ && t.types[0].flags & 32768 /* TypeFlags.Undefined */); })) { var undefinedOrMissingType = exactOptionalPropertyTypes && ts.some(typeSet, function (t) { return containsType(t.types, missingType); }) ? missingType : undefinedType; removeFromEach(typeSet, 32768 /* TypeFlags.Undefined */); result = getUnionType([getIntersectionType(typeSet), undefinedOrMissingType], 1 /* UnionReduction.Literal */, aliasSymbol, aliasTypeArguments); } - else if (eachIsUnionContaining(typeSet, 65536 /* TypeFlags.Null */)) { + else if (ts.every(typeSet, function (t) { return !!(t.flags & 1048576 /* TypeFlags.Union */ && (t.types[0].flags & 65536 /* TypeFlags.Null */ || t.types[1].flags & 65536 /* TypeFlags.Null */)); })) { removeFromEach(typeSet, 65536 /* TypeFlags.Null */); result = getUnionType([getIntersectionType(typeSet), nullType], 1 /* UnionReduction.Literal */, aliasSymbol, aliasTypeArguments); } @@ -69582,6 +69611,20 @@ var ts; if (containsType(targetTypes, source)) { return -1 /* Ternary.True */; } + if (ts.getObjectFlags(target) & 32768 /* ObjectFlags.PrimitiveUnion */ && !(source.flags & 1024 /* TypeFlags.EnumLiteral */) && (source.flags & (128 /* TypeFlags.StringLiteral */ | 512 /* TypeFlags.BooleanLiteral */ | 2048 /* TypeFlags.BigIntLiteral */) || + (relation === subtypeRelation || relation === strictSubtypeRelation) && source.flags & 256 /* TypeFlags.NumberLiteral */)) { + // When relating a literal type to a union of primitive types, we know the relation is false unless + // the union contains the base primitive type or the literal type in one of its fresh/regular forms. + // We exclude numeric literals for non-subtype relations because numeric literals are assignable to + // numeric enum literals with the same value. Similarly, we exclude enum literal types because + // identically named enum types are related (see isEmumTypeRelatedTo). + var alternateForm = source === source.regularType ? source.freshType : source.regularType; + var primitive = source.flags & 128 /* TypeFlags.StringLiteral */ ? stringType : + source.flags & 256 /* TypeFlags.NumberLiteral */ ? numberType : + source.flags & 2048 /* TypeFlags.BigIntLiteral */ ? bigintType : + undefined; + return primitive && containsType(targetTypes, primitive) || alternateForm && containsType(targetTypes, alternateForm) ? -1 /* Ternary.True */ : 0 /* Ternary.False */; + } var match = getMatchingUnionConstituentForType(target, source); if (match) { var related = isRelatedTo(source, match, 2 /* RecursionFlags.Target */, /*reportErrors*/ false); @@ -117552,6 +117595,14 @@ var ts; PipelinePhase[PipelinePhase["SourceMaps"] = 3] = "SourceMaps"; PipelinePhase[PipelinePhase["Emit"] = 4] = "Emit"; })(PipelinePhase || (PipelinePhase = {})); + /** @internal */ + ts.createPrinterWithDefaults = ts.memoize(function () { return createPrinter({}); }); + /** @internal */ + ts.createPrinterWithRemoveComments = ts.memoize(function () { return createPrinter({ removeComments: true }); }); + /** @internal */ + ts.createPrinterWithRemoveCommentsNeverAsciiEscape = ts.memoize(function () { return createPrinter({ removeComments: true, neverAsciiEscape: true }); }); + /** @internal */ + ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon = ts.memoize(function () { return createPrinter({ removeComments: true, omitTrailingSemicolon: true }); }); function createPrinter(printerOptions, handlers) { if (printerOptions === void 0) { printerOptions = {}; } if (handlers === void 0) { handlers = {}; } @@ -136780,7 +136831,7 @@ var ts; function nodeToDisplayParts(node, enclosingDeclaration) { var file = enclosingDeclaration.getSourceFile(); return mapToDisplayParts(function (writer) { - var printer = ts.createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + var printer = ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon(); printer.writeNode(4 /* EmitHint.Unspecified */, node, file, writer); }); } @@ -147509,7 +147560,7 @@ var ts; } if (text === undefined) { // get the text from printing the node on a single line without comments... - var printer_1 = ts.createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + var printer_1 = ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon(); text = ts.usingSingleLineStringWriter(function (writer) { return printer_1.writeNode(4 /* EmitHint.Unspecified */, node, node.getSourceFile(), writer); }); } return { text: text, pos: declName.getStart(), end: declName.getEnd() }; @@ -152778,7 +152829,7 @@ var ts; } function getTypeHelpItem(symbol, typeParameters, checker, enclosingDeclaration, sourceFile) { var typeSymbolDisplay = ts.symbolToDisplayParts(checker, symbol); - var printer = ts.createPrinter({ removeComments: true }); + var printer = ts.createPrinterWithRemoveComments(); var parameters = typeParameters.map(function (t) { return createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer); }); var documentation = symbol.getDocumentationComment(checker); var tags = symbol.getJsDocTags(checker); @@ -152812,7 +152863,7 @@ var ts; } function itemInfoForTypeParameters(candidateSignature, checker, enclosingDeclaration, sourceFile) { var typeParameters = (candidateSignature.target || candidateSignature).typeParameters; - var printer = ts.createPrinter({ removeComments: true }); + var printer = ts.createPrinterWithRemoveComments(); var parameters = (typeParameters || ts.emptyArray).map(function (t) { return createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer); }); var thisParameter = candidateSignature.thisParameter ? [checker.symbolToParameterDeclaration(candidateSignature.thisParameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)] : []; return checker.getExpandedParameters(candidateSignature).map(function (paramList) { @@ -152824,7 +152875,7 @@ var ts; }); } function itemInfoForParameters(candidateSignature, checker, enclosingDeclaration, sourceFile) { - var printer = ts.createPrinter({ removeComments: true }); + var printer = ts.createPrinterWithRemoveComments(); var typeParameterParts = ts.mapToDisplayParts(function (writer) { if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) { var args = ts.factory.createNodeArray(candidateSignature.typeParameters.map(function (p) { return checker.typeParameterToDeclaration(p, enclosingDeclaration, signatureHelpNodeBuilderFlags); })); @@ -153127,8 +153178,7 @@ var ts; } function printTypeInSingleLine(type) { var flags = 70221824 /* NodeBuilderFlags.IgnoreErrors */ | 1048576 /* TypeFormatFlags.AllowUniqueESSymbolType */ | 16384 /* TypeFormatFlags.UseAliasDefinedOutsideCurrentScope */; - var options = { removeComments: true }; - var printer = ts.createPrinter(options); + var printer = ts.createPrinterWithRemoveComments(); return ts.usingSingleLineStringWriter(function (writer) { var typeNode = checker.typeToTypeNode(type, /*enclosingDeclaration*/ undefined, flags, writer); ts.Debug.assertIsDefined(typeNode, "should always get typenode"); @@ -153673,7 +153723,6 @@ var ts; var hasAddedSymbolInfo = false; var isThisExpression = location.kind === 109 /* SyntaxKind.ThisKeyword */ && ts.isInExpressionContext(location) || ts.isThisInTypeQuery(location); var type; - var printer; var documentationFromAlias; var tagsFromAlias; var hasMultipleSignatures = false; @@ -154116,10 +154165,7 @@ var ts; } return { displayParts: displayParts, documentation: documentation, symbolKind: symbolKind, tags: tags.length === 0 ? undefined : tags }; function getPrinter() { - if (!printer) { - printer = ts.createPrinter({ removeComments: true }); - } - return printer; + return ts.createPrinterWithRemoveComments(); } function prefixNextMeaning() { if (displayParts.length) { diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js index 52606bf025..bbbdade316 100644 --- a/lib/typescriptServices.js +++ b/lib/typescriptServices.js @@ -5420,7 +5420,7 @@ var ts; /* @internal */ TypeFlags[TypeFlags["IncludesInstantiable"] = 33554432] = "IncludesInstantiable"; /* @internal */ - TypeFlags[TypeFlags["NotPrimitiveUnion"] = 36323363] = "NotPrimitiveUnion"; + TypeFlags[TypeFlags["NotPrimitiveUnion"] = 36323331] = "NotPrimitiveUnion"; })(TypeFlags = ts.TypeFlags || (ts.TypeFlags = {})); // Types included in TypeFlags.ObjectFlagsType have an objectFlags property. Some ObjectFlags // are specific to certain types and reuse the same bit position. Those ObjectFlags require a check @@ -39313,7 +39313,7 @@ var ts; return withJSDoc(finishNode(node, pos), hasJSDoc); } function isSetLazy(identifier) { - // 1. import lazy { export } from "mod"; + // 1. import lazy { export } from "mod"; // 2. import lazy defaultExport from "mod"; // 3. import lazy defaultExport, { export, /* ... */ } from "mod"; return (identifier === null || identifier === void 0 ? void 0 : identifier.escapedText) === 'lazy' && @@ -48417,6 +48417,7 @@ var ts; var preSwitchCaseFlow; var activeLabelList; var hasExplicitReturn; + var hasFlowEffects; // state used for emit helpers var emitFlags; // If this file is an external module, then it is automatically in strict-mode according to @@ -48480,6 +48481,7 @@ var ts; currentExceptionTarget = undefined; activeLabelList = undefined; hasExplicitReturn = false; + hasFlowEffects = false; inAssignmentPattern = false; emitFlags = 0 /* NodeFlags.None */; } @@ -49040,8 +49042,8 @@ var ts; function isNarrowingExpression(expr) { switch (expr.kind) { case 79 /* SyntaxKind.Identifier */: - case 80 /* SyntaxKind.PrivateIdentifier */: case 109 /* SyntaxKind.ThisKeyword */: + return true; case 211 /* SyntaxKind.PropertyAccessExpression */: case 212 /* SyntaxKind.ElementAccessExpression */: return containsNarrowableReference(expr); @@ -49060,11 +49062,24 @@ var ts; return false; } function isNarrowableReference(expr) { - return ts.isDottedName(expr) - || (ts.isPropertyAccessExpression(expr) || ts.isNonNullExpression(expr) || ts.isParenthesizedExpression(expr)) && isNarrowableReference(expr.expression) - || ts.isBinaryExpression(expr) && expr.operatorToken.kind === 27 /* SyntaxKind.CommaToken */ && isNarrowableReference(expr.right) - || ts.isElementAccessExpression(expr) && (ts.isStringOrNumericLiteralLike(expr.argumentExpression) || ts.isEntityNameExpression(expr.argumentExpression)) && isNarrowableReference(expr.expression) - || ts.isAssignmentExpression(expr) && isNarrowableReference(expr.left); + switch (expr.kind) { + case 79 /* SyntaxKind.Identifier */: + case 109 /* SyntaxKind.ThisKeyword */: + case 107 /* SyntaxKind.SuperKeyword */: + case 237 /* SyntaxKind.MetaProperty */: + return true; + case 211 /* SyntaxKind.PropertyAccessExpression */: + case 217 /* SyntaxKind.ParenthesizedExpression */: + case 236 /* SyntaxKind.NonNullExpression */: + return isNarrowableReference(expr.expression); + case 212 /* SyntaxKind.ElementAccessExpression */: + return (ts.isStringOrNumericLiteralLike(expr.argumentExpression) || ts.isEntityNameExpression(expr.argumentExpression)) && + isNarrowableReference(expr.expression); + case 227 /* SyntaxKind.BinaryExpression */: + return expr.operatorToken.kind === 27 /* SyntaxKind.CommaToken */ && isNarrowableReference(expr.right) || + ts.isAssignmentOperator(expr.operatorToken.kind) && ts.isLeftHandSideExpression(expr.left); + } + return false; } function containsNarrowableReference(expr) { return isNarrowableReference(expr) || ts.isOptionalChain(expr) && containsNarrowableReference(expr.expression); @@ -49166,6 +49181,7 @@ var ts; } function createFlowMutation(flags, antecedent, node) { setFlowNodeReferenced(antecedent); + hasFlowEffects = true; var result = initFlowNode({ flags: flags, antecedent: antecedent, node: node }); if (currentExceptionTarget) { addAntecedent(currentExceptionTarget, result); @@ -49174,6 +49190,7 @@ var ts; } function createFlowCall(antecedent, node) { setFlowNodeReferenced(antecedent); + hasFlowEffects = true; return initFlowNode({ flags: 512 /* FlowFlags.Call */, antecedent: antecedent, node: node }); } function finishFlowLabel(flow) { @@ -49339,6 +49356,7 @@ var ts; } } currentFlow = unreachableFlow; + hasFlowEffects = true; } function findActiveLabel(name) { for (var label = activeLabelList; label; label = label.next) { @@ -49353,6 +49371,7 @@ var ts; if (flowLabel) { addAntecedent(flowLabel, currentFlow); currentFlow = unreachableFlow; + hasFlowEffects = true; } } function bindBreakOrContinueStatement(node) { @@ -49658,8 +49677,12 @@ var ts; ts.isLogicalOrCoalescingAssignmentOperator(operator)) { if (isTopLevelLogicalExpression(node)) { var postExpressionLabel = createBranchLabel(); + var saveCurrentFlow = currentFlow; + var saveHasFlowEffects = hasFlowEffects; + hasFlowEffects = false; bindLogicalLikeExpression(node, postExpressionLabel, postExpressionLabel); - currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects || (hasFlowEffects = saveHasFlowEffects); } else { bindLogicalLikeExpression(node, currentTrueTarget, currentFalseTarget); @@ -49732,6 +49755,9 @@ var ts; var trueLabel = createBranchLabel(); var falseLabel = createBranchLabel(); var postExpressionLabel = createBranchLabel(); + var saveCurrentFlow = currentFlow; + var saveHasFlowEffects = hasFlowEffects; + hasFlowEffects = false; bindCondition(node.condition, trueLabel, falseLabel); currentFlow = finishFlowLabel(trueLabel); bind(node.questionToken); @@ -49742,6 +49768,8 @@ var ts; bind(node.whenFalse); addAntecedent(postExpressionLabel, currentFlow); currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects || (hasFlowEffects = saveHasFlowEffects); } function bindInitializedVariableFlow(node) { var name = !ts.isOmittedExpression(node) ? node.name : undefined; @@ -49863,8 +49891,11 @@ var ts; function bindOptionalChainFlow(node) { if (isTopLevelLogicalExpression(node)) { var postExpressionLabel = createBranchLabel(); + var saveCurrentFlow = currentFlow; + var saveHasFlowEffects = hasFlowEffects; bindOptionalChain(node, postExpressionLabel, postExpressionLabel); - currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects || (hasFlowEffects = saveHasFlowEffects); } else { bindOptionalChain(node, currentTrueTarget, currentFalseTarget); @@ -56268,7 +56299,9 @@ var ts; function symbolToStringWorker(writer) { var entity = builder(symbol, meaning, enclosingDeclaration, nodeFlags); // TODO: GH#18217 // add neverAsciiEscape for GH#39027 - var printer = (enclosingDeclaration === null || enclosingDeclaration === void 0 ? void 0 : enclosingDeclaration.kind) === 314 /* SyntaxKind.SourceFile */ ? ts.createPrinter({ removeComments: true, neverAsciiEscape: true }) : ts.createPrinter({ removeComments: true }); + var printer = (enclosingDeclaration === null || enclosingDeclaration === void 0 ? void 0 : enclosingDeclaration.kind) === 314 /* SyntaxKind.SourceFile */ + ? ts.createPrinterWithRemoveCommentsNeverAsciiEscape() + : ts.createPrinterWithRemoveComments(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, entity, /*sourceFile*/ sourceFile, writer); return writer; @@ -56286,7 +56319,7 @@ var ts; sigOutput = kind === 1 /* SignatureKind.Construct */ ? 180 /* SyntaxKind.ConstructSignature */ : 179 /* SyntaxKind.CallSignature */; } var sig = nodeBuilder.signatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, toNodeBuilderFlags(flags) | 70221824 /* NodeBuilderFlags.IgnoreErrors */ | 512 /* NodeBuilderFlags.WriteTypeParametersInQualifiedName */); - var printer = ts.createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + var printer = ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, sig, /*sourceFile*/ sourceFile, ts.getTrailingSemicolonDeferringWriter(writer)); // TODO: GH#18217 return writer; @@ -56301,8 +56334,7 @@ var ts; return ts.Debug.fail("should always get typenode"); // The unresolved type gets a synthesized comment on `any` to hint to users that it's not a plain `any`. // Otherwise, we always strip comments out. - var options = { removeComments: type !== unresolvedType }; - var printer = ts.createPrinter(options); + var printer = type !== unresolvedType ? ts.createPrinterWithRemoveComments() : ts.createPrinterWithDefaults(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, typeNode, /*sourceFile*/ sourceFile, writer); var result = writer.getText(); @@ -59378,7 +59410,7 @@ var ts; function typePredicateToStringWorker(writer) { var predicate = ts.factory.createTypePredicateNode(typePredicate.kind === 2 /* TypePredicateKind.AssertsThis */ || typePredicate.kind === 3 /* TypePredicateKind.AssertsIdentifier */ ? ts.factory.createToken(130 /* SyntaxKind.AssertsKeyword */) : undefined, typePredicate.kind === 1 /* TypePredicateKind.Identifier */ || typePredicate.kind === 3 /* TypePredicateKind.AssertsIdentifier */ ? ts.factory.createIdentifier(typePredicate.parameterName) : ts.factory.createThisTypeNode(), typePredicate.type && nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | 70221824 /* NodeBuilderFlags.IgnoreErrors */ | 512 /* NodeBuilderFlags.WriteTypeParametersInQualifiedName */) // TODO: GH#18217 ); - var printer = ts.createPrinter({ removeComments: true }); + var printer = ts.createPrinterWithRemoveComments(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, predicate, /*sourceFile*/ sourceFile, writer); return writer; @@ -65511,7 +65543,7 @@ var ts; origin = createOriginUnionOrIntersectionType(1048576 /* TypeFlags.Union */, reducedTypes); } } - var objectFlags = (includes & 36323363 /* TypeFlags.NotPrimitiveUnion */ ? 0 : 32768 /* ObjectFlags.PrimitiveUnion */) | + var objectFlags = (includes & 36323331 /* TypeFlags.NotPrimitiveUnion */ ? 0 : 32768 /* ObjectFlags.PrimitiveUnion */) | (includes & 2097152 /* TypeFlags.Intersection */ ? 16777216 /* ObjectFlags.ContainsIntersections */ : 0); return getUnionTypeFromSortedList(typeSet, objectFlags, aliasSymbol, aliasTypeArguments, origin); } @@ -65654,7 +65686,7 @@ var ts; var u = unionTypes_1[_i]; if (!containsType(u.types, type)) { var primitive = type.flags & 128 /* TypeFlags.StringLiteral */ ? stringType : - type.flags & 256 /* TypeFlags.NumberLiteral */ ? numberType : + type.flags & (32 /* TypeFlags.Enum */ | 256 /* TypeFlags.NumberLiteral */) ? numberType : type.flags & 2048 /* TypeFlags.BigIntLiteral */ ? bigintType : type.flags & 8192 /* TypeFlags.UniqueESSymbol */ ? esSymbolType : undefined; @@ -65690,9 +65722,6 @@ var ts; } return false; } - function eachIsUnionContaining(types, flag) { - return ts.every(types, function (t) { return !!(t.flags & 1048576 /* TypeFlags.Union */) && ts.some(t.types, function (tt) { return !!(tt.flags & flag); }); }); - } function removeFromEach(types, flag) { for (var i = 0; i < types.length; i++) { types[i] = filterType(types[i], function (t) { return !(t.flags & flag); }); @@ -65824,12 +65853,12 @@ var ts; // reduced we'll never reduce again, so this occurs at most once. result = getIntersectionType(typeSet, aliasSymbol, aliasTypeArguments); } - else if (eachIsUnionContaining(typeSet, 32768 /* TypeFlags.Undefined */)) { + else if (ts.every(typeSet, function (t) { return !!(t.flags & 1048576 /* TypeFlags.Union */ && t.types[0].flags & 32768 /* TypeFlags.Undefined */); })) { var undefinedOrMissingType = exactOptionalPropertyTypes && ts.some(typeSet, function (t) { return containsType(t.types, missingType); }) ? missingType : undefinedType; removeFromEach(typeSet, 32768 /* TypeFlags.Undefined */); result = getUnionType([getIntersectionType(typeSet), undefinedOrMissingType], 1 /* UnionReduction.Literal */, aliasSymbol, aliasTypeArguments); } - else if (eachIsUnionContaining(typeSet, 65536 /* TypeFlags.Null */)) { + else if (ts.every(typeSet, function (t) { return !!(t.flags & 1048576 /* TypeFlags.Union */ && (t.types[0].flags & 65536 /* TypeFlags.Null */ || t.types[1].flags & 65536 /* TypeFlags.Null */)); })) { removeFromEach(typeSet, 65536 /* TypeFlags.Null */); result = getUnionType([getIntersectionType(typeSet), nullType], 1 /* UnionReduction.Literal */, aliasSymbol, aliasTypeArguments); } @@ -69582,6 +69611,20 @@ var ts; if (containsType(targetTypes, source)) { return -1 /* Ternary.True */; } + if (ts.getObjectFlags(target) & 32768 /* ObjectFlags.PrimitiveUnion */ && !(source.flags & 1024 /* TypeFlags.EnumLiteral */) && (source.flags & (128 /* TypeFlags.StringLiteral */ | 512 /* TypeFlags.BooleanLiteral */ | 2048 /* TypeFlags.BigIntLiteral */) || + (relation === subtypeRelation || relation === strictSubtypeRelation) && source.flags & 256 /* TypeFlags.NumberLiteral */)) { + // When relating a literal type to a union of primitive types, we know the relation is false unless + // the union contains the base primitive type or the literal type in one of its fresh/regular forms. + // We exclude numeric literals for non-subtype relations because numeric literals are assignable to + // numeric enum literals with the same value. Similarly, we exclude enum literal types because + // identically named enum types are related (see isEmumTypeRelatedTo). + var alternateForm = source === source.regularType ? source.freshType : source.regularType; + var primitive = source.flags & 128 /* TypeFlags.StringLiteral */ ? stringType : + source.flags & 256 /* TypeFlags.NumberLiteral */ ? numberType : + source.flags & 2048 /* TypeFlags.BigIntLiteral */ ? bigintType : + undefined; + return primitive && containsType(targetTypes, primitive) || alternateForm && containsType(targetTypes, alternateForm) ? -1 /* Ternary.True */ : 0 /* Ternary.False */; + } var match = getMatchingUnionConstituentForType(target, source); if (match) { var related = isRelatedTo(source, match, 2 /* RecursionFlags.Target */, /*reportErrors*/ false); @@ -117552,6 +117595,14 @@ var ts; PipelinePhase[PipelinePhase["SourceMaps"] = 3] = "SourceMaps"; PipelinePhase[PipelinePhase["Emit"] = 4] = "Emit"; })(PipelinePhase || (PipelinePhase = {})); + /** @internal */ + ts.createPrinterWithDefaults = ts.memoize(function () { return createPrinter({}); }); + /** @internal */ + ts.createPrinterWithRemoveComments = ts.memoize(function () { return createPrinter({ removeComments: true }); }); + /** @internal */ + ts.createPrinterWithRemoveCommentsNeverAsciiEscape = ts.memoize(function () { return createPrinter({ removeComments: true, neverAsciiEscape: true }); }); + /** @internal */ + ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon = ts.memoize(function () { return createPrinter({ removeComments: true, omitTrailingSemicolon: true }); }); function createPrinter(printerOptions, handlers) { if (printerOptions === void 0) { printerOptions = {}; } if (handlers === void 0) { handlers = {}; } @@ -136780,7 +136831,7 @@ var ts; function nodeToDisplayParts(node, enclosingDeclaration) { var file = enclosingDeclaration.getSourceFile(); return mapToDisplayParts(function (writer) { - var printer = ts.createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + var printer = ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon(); printer.writeNode(4 /* EmitHint.Unspecified */, node, file, writer); }); } @@ -147509,7 +147560,7 @@ var ts; } if (text === undefined) { // get the text from printing the node on a single line without comments... - var printer_1 = ts.createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + var printer_1 = ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon(); text = ts.usingSingleLineStringWriter(function (writer) { return printer_1.writeNode(4 /* EmitHint.Unspecified */, node, node.getSourceFile(), writer); }); } return { text: text, pos: declName.getStart(), end: declName.getEnd() }; @@ -152778,7 +152829,7 @@ var ts; } function getTypeHelpItem(symbol, typeParameters, checker, enclosingDeclaration, sourceFile) { var typeSymbolDisplay = ts.symbolToDisplayParts(checker, symbol); - var printer = ts.createPrinter({ removeComments: true }); + var printer = ts.createPrinterWithRemoveComments(); var parameters = typeParameters.map(function (t) { return createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer); }); var documentation = symbol.getDocumentationComment(checker); var tags = symbol.getJsDocTags(checker); @@ -152812,7 +152863,7 @@ var ts; } function itemInfoForTypeParameters(candidateSignature, checker, enclosingDeclaration, sourceFile) { var typeParameters = (candidateSignature.target || candidateSignature).typeParameters; - var printer = ts.createPrinter({ removeComments: true }); + var printer = ts.createPrinterWithRemoveComments(); var parameters = (typeParameters || ts.emptyArray).map(function (t) { return createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer); }); var thisParameter = candidateSignature.thisParameter ? [checker.symbolToParameterDeclaration(candidateSignature.thisParameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)] : []; return checker.getExpandedParameters(candidateSignature).map(function (paramList) { @@ -152824,7 +152875,7 @@ var ts; }); } function itemInfoForParameters(candidateSignature, checker, enclosingDeclaration, sourceFile) { - var printer = ts.createPrinter({ removeComments: true }); + var printer = ts.createPrinterWithRemoveComments(); var typeParameterParts = ts.mapToDisplayParts(function (writer) { if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) { var args = ts.factory.createNodeArray(candidateSignature.typeParameters.map(function (p) { return checker.typeParameterToDeclaration(p, enclosingDeclaration, signatureHelpNodeBuilderFlags); })); @@ -153127,8 +153178,7 @@ var ts; } function printTypeInSingleLine(type) { var flags = 70221824 /* NodeBuilderFlags.IgnoreErrors */ | 1048576 /* TypeFormatFlags.AllowUniqueESSymbolType */ | 16384 /* TypeFormatFlags.UseAliasDefinedOutsideCurrentScope */; - var options = { removeComments: true }; - var printer = ts.createPrinter(options); + var printer = ts.createPrinterWithRemoveComments(); return ts.usingSingleLineStringWriter(function (writer) { var typeNode = checker.typeToTypeNode(type, /*enclosingDeclaration*/ undefined, flags, writer); ts.Debug.assertIsDefined(typeNode, "should always get typenode"); @@ -153673,7 +153723,6 @@ var ts; var hasAddedSymbolInfo = false; var isThisExpression = location.kind === 109 /* SyntaxKind.ThisKeyword */ && ts.isInExpressionContext(location) || ts.isThisInTypeQuery(location); var type; - var printer; var documentationFromAlias; var tagsFromAlias; var hasMultipleSignatures = false; @@ -154116,10 +154165,7 @@ var ts; } return { displayParts: displayParts, documentation: documentation, symbolKind: symbolKind, tags: tags.length === 0 ? undefined : tags }; function getPrinter() { - if (!printer) { - printer = ts.createPrinter({ removeComments: true }); - } - return printer; + return ts.createPrinterWithRemoveComments(); } function prefixNextMeaning() { if (displayParts.length) { diff --git a/lib/typingsInstaller.js b/lib/typingsInstaller.js index d7a5353268..1ab6419fcf 100644 --- a/lib/typingsInstaller.js +++ b/lib/typingsInstaller.js @@ -5410,7 +5410,7 @@ var ts; /* @internal */ TypeFlags[TypeFlags["IncludesInstantiable"] = 33554432] = "IncludesInstantiable"; /* @internal */ - TypeFlags[TypeFlags["NotPrimitiveUnion"] = 36323363] = "NotPrimitiveUnion"; + TypeFlags[TypeFlags["NotPrimitiveUnion"] = 36323331] = "NotPrimitiveUnion"; })(TypeFlags = ts.TypeFlags || (ts.TypeFlags = {})); // Types included in TypeFlags.ObjectFlagsType have an objectFlags property. Some ObjectFlags // are specific to certain types and reuse the same bit position. Those ObjectFlags require a check @@ -39303,7 +39303,7 @@ var ts; return withJSDoc(finishNode(node, pos), hasJSDoc); } function isSetLazy(identifier) { - // 1. import lazy { export } from "mod"; + // 1. import lazy { export } from "mod"; // 2. import lazy defaultExport from "mod"; // 3. import lazy defaultExport, { export, /* ... */ } from "mod"; return (identifier === null || identifier === void 0 ? void 0 : identifier.escapedText) === 'lazy' && @@ -48407,6 +48407,7 @@ var ts; var preSwitchCaseFlow; var activeLabelList; var hasExplicitReturn; + var hasFlowEffects; // state used for emit helpers var emitFlags; // If this file is an external module, then it is automatically in strict-mode according to @@ -48470,6 +48471,7 @@ var ts; currentExceptionTarget = undefined; activeLabelList = undefined; hasExplicitReturn = false; + hasFlowEffects = false; inAssignmentPattern = false; emitFlags = 0 /* NodeFlags.None */; } @@ -49030,8 +49032,8 @@ var ts; function isNarrowingExpression(expr) { switch (expr.kind) { case 79 /* SyntaxKind.Identifier */: - case 80 /* SyntaxKind.PrivateIdentifier */: case 109 /* SyntaxKind.ThisKeyword */: + return true; case 211 /* SyntaxKind.PropertyAccessExpression */: case 212 /* SyntaxKind.ElementAccessExpression */: return containsNarrowableReference(expr); @@ -49050,11 +49052,24 @@ var ts; return false; } function isNarrowableReference(expr) { - return ts.isDottedName(expr) - || (ts.isPropertyAccessExpression(expr) || ts.isNonNullExpression(expr) || ts.isParenthesizedExpression(expr)) && isNarrowableReference(expr.expression) - || ts.isBinaryExpression(expr) && expr.operatorToken.kind === 27 /* SyntaxKind.CommaToken */ && isNarrowableReference(expr.right) - || ts.isElementAccessExpression(expr) && (ts.isStringOrNumericLiteralLike(expr.argumentExpression) || ts.isEntityNameExpression(expr.argumentExpression)) && isNarrowableReference(expr.expression) - || ts.isAssignmentExpression(expr) && isNarrowableReference(expr.left); + switch (expr.kind) { + case 79 /* SyntaxKind.Identifier */: + case 109 /* SyntaxKind.ThisKeyword */: + case 107 /* SyntaxKind.SuperKeyword */: + case 237 /* SyntaxKind.MetaProperty */: + return true; + case 211 /* SyntaxKind.PropertyAccessExpression */: + case 217 /* SyntaxKind.ParenthesizedExpression */: + case 236 /* SyntaxKind.NonNullExpression */: + return isNarrowableReference(expr.expression); + case 212 /* SyntaxKind.ElementAccessExpression */: + return (ts.isStringOrNumericLiteralLike(expr.argumentExpression) || ts.isEntityNameExpression(expr.argumentExpression)) && + isNarrowableReference(expr.expression); + case 227 /* SyntaxKind.BinaryExpression */: + return expr.operatorToken.kind === 27 /* SyntaxKind.CommaToken */ && isNarrowableReference(expr.right) || + ts.isAssignmentOperator(expr.operatorToken.kind) && ts.isLeftHandSideExpression(expr.left); + } + return false; } function containsNarrowableReference(expr) { return isNarrowableReference(expr) || ts.isOptionalChain(expr) && containsNarrowableReference(expr.expression); @@ -49156,6 +49171,7 @@ var ts; } function createFlowMutation(flags, antecedent, node) { setFlowNodeReferenced(antecedent); + hasFlowEffects = true; var result = initFlowNode({ flags: flags, antecedent: antecedent, node: node }); if (currentExceptionTarget) { addAntecedent(currentExceptionTarget, result); @@ -49164,6 +49180,7 @@ var ts; } function createFlowCall(antecedent, node) { setFlowNodeReferenced(antecedent); + hasFlowEffects = true; return initFlowNode({ flags: 512 /* FlowFlags.Call */, antecedent: antecedent, node: node }); } function finishFlowLabel(flow) { @@ -49329,6 +49346,7 @@ var ts; } } currentFlow = unreachableFlow; + hasFlowEffects = true; } function findActiveLabel(name) { for (var label = activeLabelList; label; label = label.next) { @@ -49343,6 +49361,7 @@ var ts; if (flowLabel) { addAntecedent(flowLabel, currentFlow); currentFlow = unreachableFlow; + hasFlowEffects = true; } } function bindBreakOrContinueStatement(node) { @@ -49648,8 +49667,12 @@ var ts; ts.isLogicalOrCoalescingAssignmentOperator(operator)) { if (isTopLevelLogicalExpression(node)) { var postExpressionLabel = createBranchLabel(); + var saveCurrentFlow = currentFlow; + var saveHasFlowEffects = hasFlowEffects; + hasFlowEffects = false; bindLogicalLikeExpression(node, postExpressionLabel, postExpressionLabel); - currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects || (hasFlowEffects = saveHasFlowEffects); } else { bindLogicalLikeExpression(node, currentTrueTarget, currentFalseTarget); @@ -49722,6 +49745,9 @@ var ts; var trueLabel = createBranchLabel(); var falseLabel = createBranchLabel(); var postExpressionLabel = createBranchLabel(); + var saveCurrentFlow = currentFlow; + var saveHasFlowEffects = hasFlowEffects; + hasFlowEffects = false; bindCondition(node.condition, trueLabel, falseLabel); currentFlow = finishFlowLabel(trueLabel); bind(node.questionToken); @@ -49732,6 +49758,8 @@ var ts; bind(node.whenFalse); addAntecedent(postExpressionLabel, currentFlow); currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects || (hasFlowEffects = saveHasFlowEffects); } function bindInitializedVariableFlow(node) { var name = !ts.isOmittedExpression(node) ? node.name : undefined; @@ -49853,8 +49881,11 @@ var ts; function bindOptionalChainFlow(node) { if (isTopLevelLogicalExpression(node)) { var postExpressionLabel = createBranchLabel(); + var saveCurrentFlow = currentFlow; + var saveHasFlowEffects = hasFlowEffects; bindOptionalChain(node, postExpressionLabel, postExpressionLabel); - currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects || (hasFlowEffects = saveHasFlowEffects); } else { bindOptionalChain(node, currentTrueTarget, currentFalseTarget); @@ -56258,7 +56289,9 @@ var ts; function symbolToStringWorker(writer) { var entity = builder(symbol, meaning, enclosingDeclaration, nodeFlags); // TODO: GH#18217 // add neverAsciiEscape for GH#39027 - var printer = (enclosingDeclaration === null || enclosingDeclaration === void 0 ? void 0 : enclosingDeclaration.kind) === 314 /* SyntaxKind.SourceFile */ ? ts.createPrinter({ removeComments: true, neverAsciiEscape: true }) : ts.createPrinter({ removeComments: true }); + var printer = (enclosingDeclaration === null || enclosingDeclaration === void 0 ? void 0 : enclosingDeclaration.kind) === 314 /* SyntaxKind.SourceFile */ + ? ts.createPrinterWithRemoveCommentsNeverAsciiEscape() + : ts.createPrinterWithRemoveComments(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, entity, /*sourceFile*/ sourceFile, writer); return writer; @@ -56276,7 +56309,7 @@ var ts; sigOutput = kind === 1 /* SignatureKind.Construct */ ? 180 /* SyntaxKind.ConstructSignature */ : 179 /* SyntaxKind.CallSignature */; } var sig = nodeBuilder.signatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, toNodeBuilderFlags(flags) | 70221824 /* NodeBuilderFlags.IgnoreErrors */ | 512 /* NodeBuilderFlags.WriteTypeParametersInQualifiedName */); - var printer = ts.createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + var printer = ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, sig, /*sourceFile*/ sourceFile, ts.getTrailingSemicolonDeferringWriter(writer)); // TODO: GH#18217 return writer; @@ -56291,8 +56324,7 @@ var ts; return ts.Debug.fail("should always get typenode"); // The unresolved type gets a synthesized comment on `any` to hint to users that it's not a plain `any`. // Otherwise, we always strip comments out. - var options = { removeComments: type !== unresolvedType }; - var printer = ts.createPrinter(options); + var printer = type !== unresolvedType ? ts.createPrinterWithRemoveComments() : ts.createPrinterWithDefaults(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, typeNode, /*sourceFile*/ sourceFile, writer); var result = writer.getText(); @@ -59368,7 +59400,7 @@ var ts; function typePredicateToStringWorker(writer) { var predicate = ts.factory.createTypePredicateNode(typePredicate.kind === 2 /* TypePredicateKind.AssertsThis */ || typePredicate.kind === 3 /* TypePredicateKind.AssertsIdentifier */ ? ts.factory.createToken(130 /* SyntaxKind.AssertsKeyword */) : undefined, typePredicate.kind === 1 /* TypePredicateKind.Identifier */ || typePredicate.kind === 3 /* TypePredicateKind.AssertsIdentifier */ ? ts.factory.createIdentifier(typePredicate.parameterName) : ts.factory.createThisTypeNode(), typePredicate.type && nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | 70221824 /* NodeBuilderFlags.IgnoreErrors */ | 512 /* NodeBuilderFlags.WriteTypeParametersInQualifiedName */) // TODO: GH#18217 ); - var printer = ts.createPrinter({ removeComments: true }); + var printer = ts.createPrinterWithRemoveComments(); var sourceFile = enclosingDeclaration && ts.getSourceFileOfNode(enclosingDeclaration); printer.writeNode(4 /* EmitHint.Unspecified */, predicate, /*sourceFile*/ sourceFile, writer); return writer; @@ -65501,7 +65533,7 @@ var ts; origin = createOriginUnionOrIntersectionType(1048576 /* TypeFlags.Union */, reducedTypes); } } - var objectFlags = (includes & 36323363 /* TypeFlags.NotPrimitiveUnion */ ? 0 : 32768 /* ObjectFlags.PrimitiveUnion */) | + var objectFlags = (includes & 36323331 /* TypeFlags.NotPrimitiveUnion */ ? 0 : 32768 /* ObjectFlags.PrimitiveUnion */) | (includes & 2097152 /* TypeFlags.Intersection */ ? 16777216 /* ObjectFlags.ContainsIntersections */ : 0); return getUnionTypeFromSortedList(typeSet, objectFlags, aliasSymbol, aliasTypeArguments, origin); } @@ -65644,7 +65676,7 @@ var ts; var u = unionTypes_1[_i]; if (!containsType(u.types, type)) { var primitive = type.flags & 128 /* TypeFlags.StringLiteral */ ? stringType : - type.flags & 256 /* TypeFlags.NumberLiteral */ ? numberType : + type.flags & (32 /* TypeFlags.Enum */ | 256 /* TypeFlags.NumberLiteral */) ? numberType : type.flags & 2048 /* TypeFlags.BigIntLiteral */ ? bigintType : type.flags & 8192 /* TypeFlags.UniqueESSymbol */ ? esSymbolType : undefined; @@ -65680,9 +65712,6 @@ var ts; } return false; } - function eachIsUnionContaining(types, flag) { - return ts.every(types, function (t) { return !!(t.flags & 1048576 /* TypeFlags.Union */) && ts.some(t.types, function (tt) { return !!(tt.flags & flag); }); }); - } function removeFromEach(types, flag) { for (var i = 0; i < types.length; i++) { types[i] = filterType(types[i], function (t) { return !(t.flags & flag); }); @@ -65814,12 +65843,12 @@ var ts; // reduced we'll never reduce again, so this occurs at most once. result = getIntersectionType(typeSet, aliasSymbol, aliasTypeArguments); } - else if (eachIsUnionContaining(typeSet, 32768 /* TypeFlags.Undefined */)) { + else if (ts.every(typeSet, function (t) { return !!(t.flags & 1048576 /* TypeFlags.Union */ && t.types[0].flags & 32768 /* TypeFlags.Undefined */); })) { var undefinedOrMissingType = exactOptionalPropertyTypes && ts.some(typeSet, function (t) { return containsType(t.types, missingType); }) ? missingType : undefinedType; removeFromEach(typeSet, 32768 /* TypeFlags.Undefined */); result = getUnionType([getIntersectionType(typeSet), undefinedOrMissingType], 1 /* UnionReduction.Literal */, aliasSymbol, aliasTypeArguments); } - else if (eachIsUnionContaining(typeSet, 65536 /* TypeFlags.Null */)) { + else if (ts.every(typeSet, function (t) { return !!(t.flags & 1048576 /* TypeFlags.Union */ && (t.types[0].flags & 65536 /* TypeFlags.Null */ || t.types[1].flags & 65536 /* TypeFlags.Null */)); })) { removeFromEach(typeSet, 65536 /* TypeFlags.Null */); result = getUnionType([getIntersectionType(typeSet), nullType], 1 /* UnionReduction.Literal */, aliasSymbol, aliasTypeArguments); } @@ -69572,6 +69601,20 @@ var ts; if (containsType(targetTypes, source)) { return -1 /* Ternary.True */; } + if (ts.getObjectFlags(target) & 32768 /* ObjectFlags.PrimitiveUnion */ && !(source.flags & 1024 /* TypeFlags.EnumLiteral */) && (source.flags & (128 /* TypeFlags.StringLiteral */ | 512 /* TypeFlags.BooleanLiteral */ | 2048 /* TypeFlags.BigIntLiteral */) || + (relation === subtypeRelation || relation === strictSubtypeRelation) && source.flags & 256 /* TypeFlags.NumberLiteral */)) { + // When relating a literal type to a union of primitive types, we know the relation is false unless + // the union contains the base primitive type or the literal type in one of its fresh/regular forms. + // We exclude numeric literals for non-subtype relations because numeric literals are assignable to + // numeric enum literals with the same value. Similarly, we exclude enum literal types because + // identically named enum types are related (see isEmumTypeRelatedTo). + var alternateForm = source === source.regularType ? source.freshType : source.regularType; + var primitive = source.flags & 128 /* TypeFlags.StringLiteral */ ? stringType : + source.flags & 256 /* TypeFlags.NumberLiteral */ ? numberType : + source.flags & 2048 /* TypeFlags.BigIntLiteral */ ? bigintType : + undefined; + return primitive && containsType(targetTypes, primitive) || alternateForm && containsType(targetTypes, alternateForm) ? -1 /* Ternary.True */ : 0 /* Ternary.False */; + } var match = getMatchingUnionConstituentForType(target, source); if (match) { var related = isRelatedTo(source, match, 2 /* RecursionFlags.Target */, /*reportErrors*/ false); @@ -117542,6 +117585,14 @@ var ts; PipelinePhase[PipelinePhase["SourceMaps"] = 3] = "SourceMaps"; PipelinePhase[PipelinePhase["Emit"] = 4] = "Emit"; })(PipelinePhase || (PipelinePhase = {})); + /** @internal */ + ts.createPrinterWithDefaults = ts.memoize(function () { return createPrinter({}); }); + /** @internal */ + ts.createPrinterWithRemoveComments = ts.memoize(function () { return createPrinter({ removeComments: true }); }); + /** @internal */ + ts.createPrinterWithRemoveCommentsNeverAsciiEscape = ts.memoize(function () { return createPrinter({ removeComments: true, neverAsciiEscape: true }); }); + /** @internal */ + ts.createPrinterWithRemoveCommentsOmitTrailingSemicolon = ts.memoize(function () { return createPrinter({ removeComments: true, omitTrailingSemicolon: true }); }); function createPrinter(printerOptions, handlers) { if (printerOptions === void 0) { printerOptions = {}; } if (handlers === void 0) { handlers = {}; } diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 10946675ff..23dde575ca 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -207,6 +207,7 @@ namespace ts { let preSwitchCaseFlow: FlowNode | undefined; let activeLabelList: ActiveLabel | undefined; let hasExplicitReturn: boolean; + var hasFlowEffects: boolean; // state used for emit helpers let emitFlags: NodeFlags; @@ -282,6 +283,7 @@ namespace ts { currentExceptionTarget = undefined; activeLabelList = undefined; hasExplicitReturn = false; + hasFlowEffects = false; inAssignmentPattern = false; emitFlags = NodeFlags.None; } @@ -875,8 +877,8 @@ namespace ts { function isNarrowingExpression(expr: Expression): boolean { switch (expr.kind) { case SyntaxKind.Identifier: - case SyntaxKind.PrivateIdentifier: case SyntaxKind.ThisKeyword: + return true; case SyntaxKind.PropertyAccessExpression: case SyntaxKind.ElementAccessExpression: return containsNarrowableReference(expr); @@ -896,11 +898,24 @@ namespace ts { } function isNarrowableReference(expr: Expression): boolean { - return isDottedName(expr) - || (isPropertyAccessExpression(expr) || isNonNullExpression(expr) || isParenthesizedExpression(expr)) && isNarrowableReference(expr.expression) - || isBinaryExpression(expr) && expr.operatorToken.kind === SyntaxKind.CommaToken && isNarrowableReference(expr.right) - || isElementAccessExpression(expr) && (isStringOrNumericLiteralLike(expr.argumentExpression) || isEntityNameExpression(expr.argumentExpression)) && isNarrowableReference(expr.expression) - || isAssignmentExpression(expr) && isNarrowableReference(expr.left); + switch (expr.kind) { + case SyntaxKind.Identifier: + case SyntaxKind.ThisKeyword: + case SyntaxKind.SuperKeyword: + case SyntaxKind.MetaProperty: + return true; + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.NonNullExpression: + return isNarrowableReference((expr as PropertyAccessExpression | ParenthesizedExpression | NonNullExpression).expression); + case SyntaxKind.ElementAccessExpression: + return (isStringOrNumericLiteralLike((expr as ElementAccessExpression).argumentExpression) || isEntityNameExpression((expr as ElementAccessExpression).argumentExpression)) && + isNarrowableReference((expr as ElementAccessExpression).expression); + case SyntaxKind.BinaryExpression: + return (expr as BinaryExpression).operatorToken.kind === SyntaxKind.CommaToken && isNarrowableReference((expr as BinaryExpression).right) || + isAssignmentOperator((expr as BinaryExpression).operatorToken.kind) && isLeftHandSideExpression((expr as BinaryExpression).left); + } + return false; } function containsNarrowableReference(expr: Expression): boolean { @@ -1014,6 +1029,7 @@ namespace ts { function createFlowMutation(flags: FlowFlags, antecedent: FlowNode, node: Expression | VariableDeclaration | ArrayBindingElement): FlowNode { setFlowNodeReferenced(antecedent); + hasFlowEffects = true; const result = initFlowNode({ flags, antecedent, node }); if (currentExceptionTarget) { addAntecedent(currentExceptionTarget, result); @@ -1023,6 +1039,7 @@ namespace ts { function createFlowCall(antecedent: FlowNode, node: CallExpression): FlowNode { setFlowNodeReferenced(antecedent); + hasFlowEffects = true; return initFlowNode({ flags: FlowFlags.Call, antecedent, node }); } @@ -1204,6 +1221,7 @@ namespace ts { } } currentFlow = unreachableFlow; + hasFlowEffects = true; } function findActiveLabel(name: __String) { @@ -1220,6 +1238,7 @@ namespace ts { if (flowLabel) { addAntecedent(flowLabel, currentFlow); currentFlow = unreachableFlow; + hasFlowEffects = true; } } @@ -1548,8 +1567,12 @@ namespace ts { isLogicalOrCoalescingAssignmentOperator(operator)) { if (isTopLevelLogicalExpression(node)) { const postExpressionLabel = createBranchLabel(); + const saveCurrentFlow = currentFlow; + const saveHasFlowEffects = hasFlowEffects; + hasFlowEffects = false; bindLogicalLikeExpression(node, postExpressionLabel, postExpressionLabel); - currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects ||= saveHasFlowEffects; } else { bindLogicalLikeExpression(node, currentTrueTarget!, currentFalseTarget!); @@ -1629,6 +1652,9 @@ namespace ts { const trueLabel = createBranchLabel(); const falseLabel = createBranchLabel(); const postExpressionLabel = createBranchLabel(); + const saveCurrentFlow = currentFlow; + const saveHasFlowEffects = hasFlowEffects; + hasFlowEffects = false; bindCondition(node.condition, trueLabel, falseLabel); currentFlow = finishFlowLabel(trueLabel); bind(node.questionToken); @@ -1639,6 +1665,8 @@ namespace ts { bind(node.whenFalse); addAntecedent(postExpressionLabel, currentFlow); currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects ||= saveHasFlowEffects; } function bindInitializedVariableFlow(node: VariableDeclaration | ArrayBindingElement) { @@ -1770,8 +1798,11 @@ namespace ts { function bindOptionalChainFlow(node: OptionalChain) { if (isTopLevelLogicalExpression(node)) { const postExpressionLabel = createBranchLabel(); + const saveCurrentFlow = currentFlow; + const saveHasFlowEffects = hasFlowEffects; bindOptionalChain(node, postExpressionLabel, postExpressionLabel); - currentFlow = finishFlowLabel(postExpressionLabel); + currentFlow = hasFlowEffects ? finishFlowLabel(postExpressionLabel) : saveCurrentFlow; + hasFlowEffects ||= saveHasFlowEffects; } else { bindOptionalChain(node, currentTrueTarget!, currentFalseTarget!); diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0e34384675..f48a14a146 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5045,7 +5045,9 @@ namespace ts { function symbolToStringWorker(writer: EmitTextWriter) { const entity = builder(symbol, meaning!, enclosingDeclaration, nodeFlags)!; // TODO: GH#18217 // add neverAsciiEscape for GH#39027 - const printer = enclosingDeclaration?.kind === SyntaxKind.SourceFile ? createPrinter({ removeComments: true, neverAsciiEscape: true }) : createPrinter({ removeComments: true }); + const printer = enclosingDeclaration?.kind === SyntaxKind.SourceFile + ? createPrinterWithRemoveCommentsNeverAsciiEscape() + : createPrinterWithRemoveComments(); const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); printer.writeNode(EmitHint.Unspecified, entity, /*sourceFile*/ sourceFile, writer); return writer; @@ -5064,7 +5066,7 @@ namespace ts { sigOutput = kind === SignatureKind.Construct ? SyntaxKind.ConstructSignature : SyntaxKind.CallSignature; } const sig = nodeBuilder.signatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName); - const printer = createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + const printer = createPrinterWithRemoveCommentsOmitTrailingSemicolon(); const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); printer.writeNode(EmitHint.Unspecified, sig!, /*sourceFile*/ sourceFile, getTrailingSemicolonDeferringWriter(writer)); // TODO: GH#18217 return writer; @@ -5077,8 +5079,7 @@ namespace ts { if (typeNode === undefined) return Debug.fail("should always get typenode"); // The unresolved type gets a synthesized comment on `any` to hint to users that it's not a plain `any`. // Otherwise, we always strip comments out. - const options = { removeComments: type !== unresolvedType }; - const printer = createPrinter(options); + const printer = type !== unresolvedType ? createPrinterWithRemoveComments() : createPrinterWithDefaults(); const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); printer.writeNode(EmitHint.Unspecified, typeNode, /*sourceFile*/ sourceFile, writer); const result = writer.getText(); @@ -8596,7 +8597,7 @@ namespace ts { typePredicate.kind === TypePredicateKind.Identifier || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? factory.createIdentifier(typePredicate.parameterName) : factory.createThisTypeNode(), typePredicate.type && nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName)! // TODO: GH#18217 ); - const printer = createPrinter({ removeComments: true }); + const printer = createPrinterWithRemoveComments(); const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration); printer.writeNode(EmitHint.Unspecified, predicate, /*sourceFile*/ sourceFile, writer); return writer; @@ -15330,7 +15331,7 @@ namespace ts { for (const u of unionTypes) { if (!containsType(u.types, type)) { const primitive = type.flags & TypeFlags.StringLiteral ? stringType : - type.flags & TypeFlags.NumberLiteral ? numberType : + type.flags & (TypeFlags.Enum | TypeFlags.NumberLiteral) ? numberType : type.flags & TypeFlags.BigIntLiteral ? bigintType : type.flags & TypeFlags.UniqueESSymbol ? esSymbolType : undefined; @@ -15366,10 +15367,6 @@ namespace ts { return false; } - function eachIsUnionContaining(types: Type[], flag: TypeFlags) { - return every(types, t => !!(t.flags & TypeFlags.Union) && some((t as UnionType).types, tt => !!(tt.flags & flag))); - } - function removeFromEach(types: Type[], flag: TypeFlags) { for (let i = 0; i < types.length; i++) { types[i] = filterType(types[i], t => !(t.flags & flag)); @@ -15501,12 +15498,12 @@ namespace ts { // reduced we'll never reduce again, so this occurs at most once. result = getIntersectionType(typeSet, aliasSymbol, aliasTypeArguments); } - else if (eachIsUnionContaining(typeSet, TypeFlags.Undefined)) { + else if (every(typeSet, t => !!(t.flags & TypeFlags.Union && (t as UnionType).types[0].flags & TypeFlags.Undefined))) { const undefinedOrMissingType = exactOptionalPropertyTypes && some(typeSet, t => containsType((t as UnionType).types, missingType)) ? missingType : undefinedType; removeFromEach(typeSet, TypeFlags.Undefined); result = getUnionType([getIntersectionType(typeSet), undefinedOrMissingType], UnionReduction.Literal, aliasSymbol, aliasTypeArguments); } - else if (eachIsUnionContaining(typeSet, TypeFlags.Null)) { + else if (every(typeSet, t => !!(t.flags & TypeFlags.Union && ((t as UnionType).types[0].flags & TypeFlags.Null || (t as UnionType).types[1].flags & TypeFlags.Null)))) { removeFromEach(typeSet, TypeFlags.Null); result = getUnionType([getIntersectionType(typeSet), nullType], UnionReduction.Literal, aliasSymbol, aliasTypeArguments); } @@ -19546,6 +19543,21 @@ namespace ts { if (containsType(targetTypes, source)) { return Ternary.True; } + if (getObjectFlags(target) & ObjectFlags.PrimitiveUnion && !(source.flags & TypeFlags.EnumLiteral) && ( + source.flags & (TypeFlags.StringLiteral | TypeFlags.BooleanLiteral | TypeFlags.BigIntLiteral) || + (relation === subtypeRelation || relation === strictSubtypeRelation) && source.flags & TypeFlags.NumberLiteral)) { + // When relating a literal type to a union of primitive types, we know the relation is false unless + // the union contains the base primitive type or the literal type in one of its fresh/regular forms. + // We exclude numeric literals for non-subtype relations because numeric literals are assignable to + // numeric enum literals with the same value. Similarly, we exclude enum literal types because + // identically named enum types are related (see isEmumTypeRelatedTo). + const alternateForm = source === (source as StringLiteralType).regularType ? (source as StringLiteralType).freshType : (source as StringLiteralType).regularType; + const primitive = source.flags & TypeFlags.StringLiteral ? stringType : + source.flags & TypeFlags.NumberLiteral ? numberType : + source.flags & TypeFlags.BigIntLiteral ? bigintType : + undefined; + return primitive && containsType(targetTypes, primitive) || alternateForm && containsType(targetTypes, alternateForm) ? Ternary.True : Ternary.False; + } const match = getMatchingUnionConstituentForType(target as UnionType, source); if (match) { const related = isRelatedTo(source, match, RecursionFlags.Target, /*reportErrors*/ false); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index e4c0c0fcbb..0580988630 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -917,6 +917,18 @@ namespace ts { Emit, } + /** @internal */ + export const createPrinterWithDefaults = memoize(() => createPrinter({})); + + /** @internal */ + export const createPrinterWithRemoveComments = memoize(() => createPrinter({ removeComments: true })); + + /** @internal */ + export const createPrinterWithRemoveCommentsNeverAsciiEscape = memoize(() => createPrinter({ removeComments: true, neverAsciiEscape: true })); + + /** @internal */ + export const createPrinterWithRemoveCommentsOmitTrailingSemicolon = memoize(() => createPrinter({ removeComments: true, omitTrailingSemicolon: true })); + export function createPrinter(printerOptions: PrinterOptions = {}, handlers: PrintHandlers = {}): Printer { const { hasGlobalName, diff --git a/src/compiler/types.ts b/src/compiler/types.ts index dae0325c65..b6480a80fe 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5806,7 +5806,7 @@ namespace ts { /* @internal */ IncludesInstantiable = Substitution, /* @internal */ - NotPrimitiveUnion = Any | Unknown | Enum | Void | Never | Object | Intersection | IncludesInstantiable, + NotPrimitiveUnion = Any | Unknown | Void | Never | Object | Intersection | IncludesInstantiable, } export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression; diff --git a/src/services/callHierarchy.ts b/src/services/callHierarchy.ts index 705613ed53..3d033004a0 100644 --- a/src/services/callHierarchy.ts +++ b/src/services/callHierarchy.ts @@ -137,7 +137,7 @@ namespace ts.CallHierarchy { } if (text === undefined) { // get the text from printing the node on a single line without comments... - const printer = createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + const printer = createPrinterWithRemoveCommentsOmitTrailingSemicolon(); text = usingSingleLineStringWriter(writer => printer.writeNode(EmitHint.Unspecified, node, node.getSourceFile(), writer)); } return { text, pos: declName.getStart(), end: declName.getEnd() }; diff --git a/src/services/inlayHints.ts b/src/services/inlayHints.ts index 7462a2c6f2..de2e8baad4 100644 --- a/src/services/inlayHints.ts +++ b/src/services/inlayHints.ts @@ -313,8 +313,7 @@ namespace ts.InlayHints { function printTypeInSingleLine(type: Type) { const flags = NodeBuilderFlags.IgnoreErrors | TypeFormatFlags.AllowUniqueESSymbolType | TypeFormatFlags.UseAliasDefinedOutsideCurrentScope; - const options: PrinterOptions = { removeComments: true }; - const printer = createPrinter(options); + const printer = createPrinterWithRemoveComments(); return usingSingleLineStringWriter(writer => { const typeNode = checker.typeToTypeNode(type, /*enclosingDeclaration*/ undefined, flags, writer); diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 569ec1a677..cc085f0c14 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -572,7 +572,7 @@ namespace ts.SignatureHelp { function getTypeHelpItem(symbol: Symbol, typeParameters: readonly TypeParameter[], checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItem { const typeSymbolDisplay = symbolToDisplayParts(checker, symbol); - const printer = createPrinter({ removeComments: true }); + const printer = createPrinterWithRemoveComments(); const parameters = typeParameters.map(t => createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer)); const documentation = symbol.getDocumentationComment(checker); @@ -612,7 +612,7 @@ namespace ts.SignatureHelp { function itemInfoForTypeParameters(candidateSignature: Signature, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItemInfo[] { const typeParameters = (candidateSignature.target || candidateSignature).typeParameters; - const printer = createPrinter({ removeComments: true }); + const printer = createPrinterWithRemoveComments(); const parameters = (typeParameters || emptyArray).map(t => createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer)); const thisParameter = candidateSignature.thisParameter ? [checker.symbolToParameterDeclaration(candidateSignature.thisParameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)!] : []; @@ -626,7 +626,7 @@ namespace ts.SignatureHelp { } function itemInfoForParameters(candidateSignature: Signature, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItemInfo[] { - const printer = createPrinter({ removeComments: true }); + const printer = createPrinterWithRemoveComments(); const typeParameterParts = mapToDisplayParts(writer => { if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) { const args = factory.createNodeArray(candidateSignature.typeParameters.map(p => checker.typeParameterToDeclaration(p, enclosingDeclaration, signatureHelpNodeBuilderFlags)!)); diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 6f66fb7c4e..5376e8af23 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -146,7 +146,6 @@ namespace ts.SymbolDisplay { let hasAddedSymbolInfo = false; const isThisExpression = location.kind === SyntaxKind.ThisKeyword && isInExpressionContext(location) || isThisInTypeQuery(location); let type: Type | undefined; - let printer: Printer; let documentationFromAlias: SymbolDisplayPart[] | undefined; let tagsFromAlias: JSDocTagInfo[] | undefined; let hasMultipleSignatures = false; @@ -621,10 +620,7 @@ namespace ts.SymbolDisplay { return { displayParts, documentation, symbolKind, tags: tags.length === 0 ? undefined : tags }; function getPrinter() { - if (!printer) { - printer = createPrinter({ removeComments: true }); - } - return printer; + return createPrinterWithRemoveComments(); } function prefixNextMeaning() { diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 66516416db..94244dcb9e 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -2471,7 +2471,7 @@ namespace ts { export function nodeToDisplayParts(node: Node, enclosingDeclaration: Node): SymbolDisplayPart[] { const file = enclosingDeclaration.getSourceFile(); return mapToDisplayParts(writer => { - const printer = createPrinter({ removeComments: true, omitTrailingSemicolon: true }); + const printer = createPrinterWithRemoveCommentsOmitTrailingSemicolon(); printer.writeNode(EmitHint.Unspecified, node, file, writer); }); } -- Gitee