From 71db8309cf7cd7369239257973c8f80f1a773fa0 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 15 Dec 2022 16:28:08 -0800 Subject: [PATCH 01/22] Remove dead core.ts functions --- src/compiler/core.ts | 103 ------------------------------------------- 1 file changed, 103 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 8be7299567361..be6938e82feb1 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -15,30 +15,6 @@ import { UnderscoreEscapedMap, } from "./_namespaces/ts"; -/** @internal */ -export function getIterator | ReadonlyMap | undefined>(iterable: I): Iterator< - I extends ReadonlyMap ? [K, V] : - I extends ReadonlySet ? T : - I extends readonly (infer T)[] ? T : - I extends undefined ? undefined : - never>; -/** @internal */ -export function getIterator(iterable: ReadonlyMap): Iterator<[K, V]>; -/** @internal */ -export function getIterator(iterable: ReadonlyMap | undefined): Iterator<[K, V]> | undefined; -/** @internal */ -export function getIterator(iterable: readonly T[] | ReadonlySet): Iterator; -/** @internal */ -export function getIterator(iterable: readonly T[] | ReadonlySet | undefined): Iterator | undefined; -/** @internal */ -export function getIterator(iterable: readonly any[] | ReadonlySet | ReadonlyMap | undefined): Iterator | undefined { - if (iterable) { - if (isArray(iterable)) return arrayIterator(iterable); - if (iterable instanceof Map) return iterable.entries(); - if (iterable instanceof Set) return iterable.values(); - throw new Error("Iteration not supported."); - } -} /** @internal */ export const emptyArray: never[] = [] as never[]; @@ -142,31 +118,6 @@ export function zipWith(arrayA: readonly T[], arrayB: readonly U[], cal return result; } -/** @internal */ -export function zipToIterator(arrayA: readonly T[], arrayB: readonly U[]): Iterator<[T, U]> { - Debug.assertEqual(arrayA.length, arrayB.length); - let i = 0; - return { - next() { - if (i === arrayA.length) { - return { value: undefined as never, done: true }; - } - i++; - return { value: [arrayA[i - 1], arrayB[i - 1]] as [T, U], done: false }; - } - }; -} - -/** @internal */ -export function zipToMap(keys: readonly K[], values: readonly V[]): Map { - Debug.assert(keys.length === values.length); - const map = new Map(); - for (let i = 0; i < keys.length; ++i) { - map.set(keys[i], values[i]); - } - return map; -} - /** * Creates a new array with `element` interspersed in between each element of `input` * if there is more than 1 value in `input`. Otherwise, returns the existing array. @@ -642,24 +593,6 @@ export function mapDefinedEntries(map: ReadonlyMap | und return result; } -/** @internal */ -export function mapDefinedValues(set: ReadonlySet, f: (value: V1) => V2 | undefined): Set; -/** @internal */ -export function mapDefinedValues(set: ReadonlySet | undefined, f: (value: V1) => V2 | undefined): Set | undefined; -/** @internal */ -export function mapDefinedValues(set: ReadonlySet | undefined, f: (value: V1) => V2 | undefined): Set | undefined { - if (set) { - const result = new Set(); - set.forEach(value => { - const newValue = f(value); - if (newValue !== undefined) { - result.add(newValue); - } - }); - return result; - } -} - /** @internal */ export function getOrUpdate(map: Map, key: K, callback: () => V) { if (map.has(key)) { @@ -2198,42 +2131,6 @@ export function memoizeWeak(callback: (arg: A) => T): (arg: }; } -/** - * High-order function, composes functions. Note that functions are composed inside-out; - * for example, `compose(a, b)` is the equivalent of `x => b(a(x))`. - * - * @param args The functions to compose. - * - * @internal - */ -export function compose(...args: ((t: T) => T)[]): (t: T) => T; -/** @internal */ -export function compose(a: (t: T) => T, b: (t: T) => T, c: (t: T) => T, d: (t: T) => T, e: (t: T) => T): (t: T) => T { - if (!!e) { - const args: ((t: T) => T)[] = []; - for (let i = 0; i < arguments.length; i++) { - args[i] = arguments[i]; - } - - return t => reduceLeft(args, (u, f) => f(u), t); - } - else if (d) { - return t => d(c(b(a(t)))); - } - else if (c) { - return t => c(b(a(t))); - } - else if (b) { - return t => b(a(t)); - } - else if (a) { - return t => a(t); - } - else { - return t => t; - } -} - /** @internal */ export const enum AssertionLevel { None = 0, From 5b984b70e5aa2e73390a0ca67fc5c54d8bc3788e Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 15 Dec 2022 16:31:56 -0800 Subject: [PATCH 02/22] Remove fill --- src/compiler/core.ts | 9 --------- .../unittests/tsserver/completionsIncomplete.ts | 6 +++--- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index be6938e82feb1..f8bf121c8f474 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -2798,15 +2798,6 @@ export function enumerateInsertsAndDeletes(newItems: readonly T[], oldItem return hasChanges; } -/** @internal */ -export function fill(length: number, cb: (index: number) => T): T[] { - const result = Array(length); - for (let i = 0; i < length; i++) { - result[i] = cb(i); - } - return result; -} - /** @internal */ export function cartesianProduct(arrays: readonly T[][]) { const result: T[][] = []; diff --git a/src/testRunner/unittests/tsserver/completionsIncomplete.ts b/src/testRunner/unittests/tsserver/completionsIncomplete.ts index d834c5c83d7e2..41baa9505f83e 100644 --- a/src/testRunner/unittests/tsserver/completionsIncomplete.ts +++ b/src/testRunner/unittests/tsserver/completionsIncomplete.ts @@ -11,12 +11,12 @@ import { function createExportingModuleFile(path: string, exportPrefix: string, exportCount: number): File { return { path, - content: ts.fill(exportCount, i => `export const ${exportPrefix}_${i} = ${i};`).join("\n"), + content: ts.arrayOf(exportCount, i => `export const ${exportPrefix}_${i} = ${i};`).join("\n"), }; } function createExportingModuleFiles(pathPrefix: string, fileCount: number, exportCount: number, getExportPrefix: (fileIndex: number) => string): File[] { - return ts.fill(fileCount, fileIndex => createExportingModuleFile( + return ts.arrayOf(fileCount, fileIndex => createExportingModuleFile( `${pathPrefix}_${fileIndex}.ts`, getExportPrefix(fileIndex), exportCount)); @@ -98,7 +98,7 @@ describe("unittests:: tsserver:: completionsIncomplete", () => { }); it("ambient module specifier resolutions do not count against the resolution limit", () => { - const ambientFiles = ts.fill(100, (i): File => ({ + const ambientFiles = ts.arrayOf(100, (i): File => ({ path: `/lib/ambient_${i}.ts`, content: `declare module "ambient_${i}" { export const aa_${i} = ${i}; }`, })); From 514ef396048ccdd199a8a15911cc11f480578155 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 15 Dec 2022 16:38:40 -0800 Subject: [PATCH 03/22] Remove getEntries --- src/compiler/checker.ts | 5 ++--- src/compiler/commandLineParser.ts | 21 +++++++++---------- src/compiler/core.ts | 14 ------------- src/compiler/scanner.ts | 5 ++--- src/compiler/transformers/jsx.ts | 3 +-- src/compiler/tsbuildPublic.ts | 3 +-- src/compiler/utilities.ts | 5 ++--- src/compiler/watchPublic.ts | 5 ++--- src/executeCommandLine/executeCommandLine.ts | 3 +-- src/harness/fourslashImpl.ts | 4 ++-- src/harness/harnessIO.ts | 4 ++-- src/jsTyping/jsTyping.ts | 5 ++--- src/server/editorServices.ts | 5 ++--- src/server/session.ts | 3 +-- src/services/services.ts | 3 +-- src/services/transpile.ts | 3 +-- .../unittests/config/commandLineParsing.ts | 2 +- src/testRunner/unittests/moduleResolution.ts | 4 ++-- src/testRunner/unittests/tsc/helpers.ts | 4 ++-- .../unittests/tsserver/typingsInstaller.ts | 12 +++++------ src/tsserver/nodeServer.ts | 3 +-- src/typingsInstaller/nodeTypingsInstaller.ts | 3 +-- 22 files changed, 45 insertions(+), 74 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index def39591676e1..023abb380b747 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -260,7 +260,6 @@ import { getEmitScriptTarget, getEnclosingBlockScopeContainer, getEntityNameFromTypeNode, - getEntries, getErrorSpanForNode, getEscapedTextOfIdentifierOrLiteral, getESModuleInterop, @@ -1180,7 +1179,7 @@ export const enum TypeFacts { AndFactsMask = All & ~OrFactsMask, } -const typeofNEFacts: ReadonlyMap = new Map(getEntries({ +const typeofNEFacts: ReadonlyMap = new Map(Object.entries({ string: TypeFacts.TypeofNEString, number: TypeFacts.TypeofNENumber, bigint: TypeFacts.TypeofNEBigInt, @@ -1301,7 +1300,7 @@ const enum IntrinsicTypeKind { Uncapitalize } -const intrinsicTypeKinds: ReadonlyMap = new Map(getEntries({ +const intrinsicTypeKinds: ReadonlyMap = new Map(Object.entries({ Uppercase: IntrinsicTypeKind.Uppercase, Lowercase: IntrinsicTypeKind.Lowercase, Capitalize: IntrinsicTypeKind.Capitalize, diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 1e6935ca223fb..26d2a2c0a7ca7 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -46,7 +46,6 @@ import { forEachEntry, getBaseFileName, getDirectoryPath, - getEntries, getFileMatcherPatterns, getLocaleSpecificMessage, getNormalizedAbsolutePath, @@ -128,7 +127,7 @@ export const compileOnSaveCommandLineOption: CommandLineOption = { defaultValueDescription: false, }; -const jsxOptionMap = new Map(getEntries({ +const jsxOptionMap = new Map(Object.entries({ "preserve": JsxEmit.Preserve, "react-native": JsxEmit.ReactNative, "react": JsxEmit.React, @@ -240,7 +239,7 @@ export const libMap = new Map(libEntries); export const optionsForWatch: CommandLineOption[] = [ { name: "watchFile", - type: new Map(getEntries({ + type: new Map(Object.entries({ fixedpollinginterval: WatchFileKind.FixedPollingInterval, prioritypollinginterval: WatchFileKind.PriorityPollingInterval, dynamicprioritypolling: WatchFileKind.DynamicPriorityPolling, @@ -254,7 +253,7 @@ export const optionsForWatch: CommandLineOption[] = [ }, { name: "watchDirectory", - type: new Map(getEntries({ + type: new Map(Object.entries({ usefsevents: WatchDirectoryKind.UseFsEvents, fixedpollinginterval: WatchDirectoryKind.FixedPollingInterval, dynamicprioritypolling: WatchDirectoryKind.DynamicPriorityPolling, @@ -266,7 +265,7 @@ export const optionsForWatch: CommandLineOption[] = [ }, { name: "fallbackPolling", - type: new Map(getEntries({ + type: new Map(Object.entries({ fixedinterval: PollingWatchKind.FixedInterval, priorityinterval: PollingWatchKind.PriorityInterval, dynamicpriority: PollingWatchKind.DynamicPriority, @@ -501,7 +500,7 @@ export const commonOptionsWithBuild: CommandLineOption[] = [ export const targetOptionDeclaration: CommandLineOptionOfCustomType = { name: "target", shortName: "t", - type: new Map(getEntries({ + type: new Map(Object.entries({ es3: ScriptTarget.ES3, es5: ScriptTarget.ES5, es6: ScriptTarget.ES2015, @@ -530,7 +529,7 @@ export const targetOptionDeclaration: CommandLineOptionOfCustomType = { export const moduleOptionDeclaration: CommandLineOptionOfCustomType = { name: "module", shortName: "m", - type: new Map(getEntries({ + type: new Map(Object.entries({ none: ModuleKind.None, commonjs: ModuleKind.CommonJS, amd: ModuleKind.AMD, @@ -755,7 +754,7 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ }, { name: "importsNotUsedAsValues", - type: new Map(getEntries({ + type: new Map(Object.entries({ remove: ImportsNotUsedAsValues.Remove, preserve: ImportsNotUsedAsValues.Preserve, error: ImportsNotUsedAsValues.Error, @@ -960,7 +959,7 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ // Module Resolution { name: "moduleResolution", - type: new Map(getEntries({ + type: new Map(Object.entries({ // N.B. The first entry specifies the value shown in `tsc --init` node10: ModuleResolutionKind.Node10, node: ModuleResolutionKind.Node10, @@ -1255,7 +1254,7 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ }, { name: "newLine", - type: new Map(getEntries({ + type: new Map(Object.entries({ crlf: NewLineKind.CarriageReturnLineFeed, lf: NewLineKind.LineFeed })), @@ -1501,7 +1500,7 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [ }, { name: "moduleDetection", - type: new Map(getEntries({ + type: new Map(Object.entries({ auto: ModuleDetectionKind.Auto, legacy: ModuleDetectionKind.Legacy, force: ModuleDetectionKind.Force, diff --git a/src/compiler/core.ts b/src/compiler/core.ts index f8bf121c8f474..d70d21792048c 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1457,20 +1457,6 @@ export function getOwnValues(collection: MapLike | T[]): T[] { return values; } -const _entries = Object.entries || ((obj: MapLike) => { - const keys = getOwnKeys(obj); - const result: [string, T][] = Array(keys.length); - for (let i = 0; i < keys.length; i++) { - result[i] = [keys[i], obj[keys[i]]]; - } - return result; -}); - -/** @internal */ -export function getEntries(obj: MapLike): [string, T][] { - return obj ? _entries(obj) : []; -} - /** @internal */ export function arrayOf(count: number, f: (index: number) => T): T[] { const result = new Array(count); diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index bdb2fe6ef239e..db14e8710fa87 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -11,7 +11,6 @@ import { Debug, DiagnosticMessage, Diagnostics, - getEntries, identity, JSDocSyntaxKind, JsxTokenSyntaxKind, @@ -192,9 +191,9 @@ export const textToKeywordObj: MapLike = { of: SyntaxKind.OfKeyword, }; -const textToKeyword = new Map(getEntries(textToKeywordObj)); +const textToKeyword = new Map(Object.entries(textToKeywordObj)); -const textToToken = new Map(getEntries({ +const textToToken = new Map(Object.entries({ ...textToKeywordObj, "{": SyntaxKind.OpenBraceToken, "}": SyntaxKind.CloseBraceToken, diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index 2dab57966eef6..2244f815d9983 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -15,7 +15,6 @@ import { flatten, GeneratedIdentifierFlags, getEmitScriptTarget, - getEntries, getJSXImplicitImportBase, getJSXRuntimeImport, getLineAndCharacterOfPosition, @@ -636,7 +635,7 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B } } -const entities = new Map(getEntries({ +const entities = new Map(Object.entries({ quot: 0x0022, amp: 0x0026, apos: 0x0027, diff --git a/src/compiler/tsbuildPublic.ts b/src/compiler/tsbuildPublic.ts index d67b8bb3f2cd4..1c07510c35002 100644 --- a/src/compiler/tsbuildPublic.ts +++ b/src/compiler/tsbuildPublic.ts @@ -55,7 +55,6 @@ import { getBuildInfoFileVersionMap, getConfigFileParsingDiagnostics, getDirectoryPath, - getEntries, getErrorCountForSummary, getFileNamesFromConfigSpecs, getFilesInErrorForSummary, @@ -2317,7 +2316,7 @@ function watchWildCardDirectories(state: SolutionBuilderState, resolved: Resolve if (!state.watch) return; updateWatchingWildcardDirectories( getOrCreateValueMapFromConfigFileMap(state.allWatchedWildcardDirectories, resolvedPath), - new Map(getEntries(parsed.wildcardDirectories!)), + new Map(Object.entries(parsed.wildcardDirectories!)), (dir, flags) => state.watchDirectory( dir, fileOrDirectory => { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 56b18ff90056d..4fbb9a2aa40be 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -157,7 +157,6 @@ import { getCombinedModifierFlags, getCombinedNodeFlags, getDirectoryPath, - getEntries, getJSDocAugmentsTag, getJSDocDeprecatedTagNoCache, getJSDocImplementsTags, @@ -5087,7 +5086,7 @@ const doubleQuoteEscapedCharsRegExp = /[\\\"\u0000-\u001f\t\v\f\b\r\n\u2028\u202 const singleQuoteEscapedCharsRegExp = /[\\\'\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g; // Template strings preserve simple LF newlines, still encode CRLF (or CR) const backtickQuoteEscapedCharsRegExp = /\r\n|[\\\`\u0000-\u001f\t\v\f\b\r\u2028\u2029\u0085]/g; -const escapedCharsMap = new Map(getEntries({ +const escapedCharsMap = new Map(Object.entries({ "\t": "\\t", "\v": "\\v", "\f": "\\f", @@ -5155,7 +5154,7 @@ export function escapeNonAsciiString(s: string, quoteChar?: CharacterCodes.doubl // the map below must be updated. const jsxDoubleQuoteEscapedCharsRegExp = /[\"\u0000-\u001f\u2028\u2029\u0085]/g; const jsxSingleQuoteEscapedCharsRegExp = /[\'\u0000-\u001f\u2028\u2029\u0085]/g; -const jsxEscapedCharsMap = new Map(getEntries({ +const jsxEscapedCharsMap = new Map(Object.entries({ "\"": """, "\'": "'" })); diff --git a/src/compiler/watchPublic.ts b/src/compiler/watchPublic.ts index 9da08decb51da..7701797d9c8a5 100644 --- a/src/compiler/watchPublic.ts +++ b/src/compiler/watchPublic.ts @@ -43,7 +43,6 @@ import { getBuildInfo, getConfigFileParsingDiagnostics, getDirectoryPath, - getEntries, getFileNamesFromConfigSpecs, getNewLineCharacter, getNormalizedAbsolutePath, @@ -1017,7 +1016,7 @@ export function createWatchProgram(host: WatchCompiler if (wildcardDirectories) { updateWatchingWildcardDirectories( watchedWildcardDirectories || (watchedWildcardDirectories = new Map()), - new Map(getEntries(wildcardDirectories)), + new Map(Object.entries(wildcardDirectories)), watchWildcardDirectory ); } @@ -1124,7 +1123,7 @@ export function createWatchProgram(host: WatchCompiler if (commandLine.parsedCommandLine?.wildcardDirectories) { updateWatchingWildcardDirectories( commandLine.watchedDirectories ||= new Map(), - new Map(getEntries(commandLine.parsedCommandLine?.wildcardDirectories)), + new Map(Object.entries(commandLine.parsedCommandLine?.wildcardDirectories)), (directory, flags) => watchDirectory( directory, fileOrDirectory => { diff --git a/src/executeCommandLine/executeCommandLine.ts b/src/executeCommandLine/executeCommandLine.ts index 0853f9c6916f4..e9a34c4dd4983 100644 --- a/src/executeCommandLine/executeCommandLine.ts +++ b/src/executeCommandLine/executeCommandLine.ts @@ -51,7 +51,6 @@ import { getCompilerOptionsDiffValue, getConfigFileParsingDiagnostics, getDiagnosticText, - getEntries, getErrorSummaryText, getLineStarts, getNormalizedAbsolutePath, @@ -400,7 +399,7 @@ function generateOptionOutput(sys: System, option: CommandLineOption, rightAlign option.type.forEach((value, name) => { (inverted[value] ||= []).push(name); }); - return getEntries(inverted) + return Object.entries(inverted) .map(([, synonyms]) => synonyms.join("/")) .join(", "); } diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 0f35cf2549a84..63b6a25a9c5d9 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -1130,7 +1130,7 @@ export class TestState { } public setTypesRegistry(map: ts.MapLike): void { - this.languageServiceAdapterHost.typesRegistry = new Map(ts.getEntries(map)); + this.languageServiceAdapterHost.typesRegistry = new Map(Object.entries(map)); } public verifyTypeOfSymbolAtLocation(range: Range, symbol: ts.Symbol, expected: string): void { @@ -3169,7 +3169,7 @@ export class TestState { public verifyBraceCompletionAtPosition(negative: boolean, openingBrace: string) { - const openBraceMap = new Map(ts.getEntries({ + const openBraceMap = new Map(Object.entries({ "(": ts.CharacterCodes.openParen, "{": ts.CharacterCodes.openBrace, "[": ts.CharacterCodes.openBracket, diff --git a/src/harness/harnessIO.ts b/src/harness/harnessIO.ts index 12cf357770963..99ed2db1136c9 100644 --- a/src/harness/harnessIO.ts +++ b/src/harness/harnessIO.ts @@ -269,7 +269,7 @@ export namespace Compiler { } if (!libFileNameSourceFileMap) { - libFileNameSourceFileMap = new Map(ts.getEntries({ + libFileNameSourceFileMap = new Map(Object.entries({ [defaultLibFileName]: createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.es5.d.ts")!, /*languageVersion*/ ts.ScriptTarget.Latest) })); } @@ -1095,7 +1095,7 @@ function getVaryByStarSettingValues(varyBy: string): ReadonlyMap; /** @internal */ export function loadSafeList(host: TypingResolutionHost, safeListPath: Path): SafeList { const result = readConfigFile(safeListPath, path => host.readFile(path)); - return new Map(getEntries(result.config)); + return new Map(Object.entries(result.config)); } /** @internal */ export function loadTypesMap(host: TypingResolutionHost, typesMapPath: Path): SafeList | undefined { const result = readConfigFile(typesMapPath, path => host.readFile(path)); if (result.config) { - return new Map(getEntries(result.config.simpleMap)); + return new Map(Object.entries(result.config.simpleMap)); } return undefined; } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index ba1e906bbfe2c..8762170c10d79 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -100,7 +100,6 @@ import { getDefaultFormatCodeSettings, getDirectoryPath, getDocumentPositionMapper, - getEntries, getFileNamesFromConfigSpecs, getFileWatcherEventKind, getNormalizedAbsolutePath, @@ -356,7 +355,7 @@ function prepareConvertersForEnumLikeCompilerOptions(commandLineOptions: Command const compilerOptionConverters = prepareConvertersForEnumLikeCompilerOptions(optionDeclarations); const watchOptionsConverters = prepareConvertersForEnumLikeCompilerOptions(optionsForWatch); -const indentStyle = new Map(getEntries({ +const indentStyle = new Map(Object.entries({ none: IndentStyle.None, block: IndentStyle.Block, smart: IndentStyle.Smart @@ -2472,7 +2471,7 @@ export class ProjectService { config!.watchedDirectoriesStale = false; updateWatchingWildcardDirectories( config!.watchedDirectories ||= new Map(), - new Map(getEntries(config!.parsedCommandLine!.wildcardDirectories!)), + new Map(Object.entries(config!.parsedCommandLine!.wildcardDirectories!)), // Create new directory watcher (directory, flags) => this.watchWildcardDirectory(directory as Path, flags, configFileName, config!), ); diff --git a/src/server/session.ts b/src/server/session.ts index 93a2874192494..16324cdac26f3 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -53,7 +53,6 @@ import { getDeclarationFromName, getDeclarationOfKind, getEmitDeclarations, - getEntries, getEntrypointsFromPackageJsonInfo, getLineAndCharacterOfPosition, getMappedContextSpan, @@ -3102,7 +3101,7 @@ export class Session implements EventSender { return { response, responseRequired: true }; } - private handlers = new Map(getEntries<(request: protocol.Request) => HandlerResponse>({ + private handlers = new Map(Object.entries<(request: protocol.Request) => HandlerResponse>({ [CommandNames.Status]: () => { const response: protocol.StatusResponseBody = { version }; return this.requiredResponse(response); diff --git a/src/services/services.ts b/src/services/services.ts index 0071e942139a6..e36785bc33ca1 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -94,7 +94,6 @@ import { getDefaultLibFileName, getDirectoryPath, getEmitDeclarations, - getEntries, getEscapedTextOfIdentifierOrLiteral, getFileEmitOutput, getImpliedNodeFormatForFile, @@ -2327,7 +2326,7 @@ export function createLanguageService( return OutliningElementsCollector.collectElements(sourceFile, cancellationToken); } - const braceMatching = new Map(getEntries({ + const braceMatching = new Map(Object.entries({ [SyntaxKind.OpenBraceToken]: SyntaxKind.CloseBraceToken, [SyntaxKind.OpenParenToken]: SyntaxKind.CloseParenToken, [SyntaxKind.OpenBracketToken]: SyntaxKind.CloseBracketToken, diff --git a/src/services/transpile.ts b/src/services/transpile.ts index 7329f788aa197..719fca06aea5b 100644 --- a/src/services/transpile.ts +++ b/src/services/transpile.ts @@ -15,7 +15,6 @@ import { forEachEntry, getDefaultCompilerOptions, getEmitScriptTarget, - getEntries, getImpliedNodeFormatForFile, getNewLineCharacter, getSetExternalModuleIndicator, @@ -117,7 +116,7 @@ export function transpileModule(input: string, transpileOptions: TranspileOption } if (transpileOptions.renamedDependencies) { - sourceFile.renamedDependencies = new Map(getEntries(transpileOptions.renamedDependencies)); + sourceFile.renamedDependencies = new Map(Object.entries(transpileOptions.renamedDependencies)); } // Output diff --git a/src/testRunner/unittests/config/commandLineParsing.ts b/src/testRunner/unittests/config/commandLineParsing.ts index 4e5c12269c937..aab17aa5178d8 100644 --- a/src/testRunner/unittests/config/commandLineParsing.ts +++ b/src/testRunner/unittests/config/commandLineParsing.ts @@ -169,7 +169,7 @@ describe("unittests:: config:: commandLineParsing:: parseCommandLine", () => { verifyNullNonIncludedOption({ subScenario: "option of type custom map", - type: () => new Map(ts.getEntries({ + type: () => new Map(Object.entries({ node: ts.ModuleResolutionKind.Node10, classic: ts.ModuleResolutionKind.Classic, })), diff --git a/src/testRunner/unittests/moduleResolution.ts b/src/testRunner/unittests/moduleResolution.ts index d48993ad4ad23..f91536d68df3f 100644 --- a/src/testRunner/unittests/moduleResolution.ts +++ b/src/testRunner/unittests/moduleResolution.ts @@ -382,7 +382,7 @@ describe("unittests:: moduleResolution:: Node module resolution - non-relative p describe("unittests:: moduleResolution:: Relative imports", () => { function test(scenario: string, filesMapLike: ts.MapLike, currentDirectory: string, rootFiles: string[], relativeNamesToCheck: string[]) { it(scenario, () => { - const files = new Map(ts.getEntries(filesMapLike)); + const files = new Map(Object.entries(filesMapLike)); const baselines: string[] = []; files.forEach((content, file) => baselines.push(`//// [${file}]\n${content}`, "")); const options: ts.CompilerOptions = { module: ts.ModuleKind.CommonJS }; @@ -464,7 +464,7 @@ describe("unittests:: moduleResolution:: Files with different casing with forceC ): void { it(scenario, () => { const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames); - let files = new Map(ts.getEntries(filesMapLike)); + let files = new Map(Object.entries(filesMapLike)); if (!useCaseSensitiveFileNames) { const oldFiles = files; files = new Map(); diff --git a/src/testRunner/unittests/tsc/helpers.ts b/src/testRunner/unittests/tsc/helpers.ts index acb23487741a5..cab632b7204dc 100644 --- a/src/testRunner/unittests/tsc/helpers.ts +++ b/src/testRunner/unittests/tsc/helpers.ts @@ -807,8 +807,8 @@ function verifyTscEditDiscrepancies({ ) { verifyPresenceAbsence(incremental, clean, `Incremental and clean do not match:: ${message}`); if (!incremental || !clean) return; - const incrementalMap = new Map(ts.getEntries(incremental)); - const cleanMap = new Map(ts.getEntries(clean)); + const incrementalMap = new Map(Object.entries(incremental)); + const cleanMap = new Map(Object.entries(clean)); cleanMap.forEach((cleanValue, key) => { const result = verifyValue(key, incrementalMap.get(key), cleanValue); if (result) addBaseline(...result); diff --git a/src/testRunner/unittests/tsserver/typingsInstaller.ts b/src/testRunner/unittests/tsserver/typingsInstaller.ts index 5071df7b4be96..2baee5315ddd4 100644 --- a/src/testRunner/unittests/tsserver/typingsInstaller.ts +++ b/src/testRunner/unittests/tsserver/typingsInstaller.ts @@ -1551,7 +1551,7 @@ describe("unittests:: tsserver:: typingsInstaller:: discover typings", () => { content: "" }; - const safeList = new Map(ts.getEntries({ jquery: "jquery", chroma: "chroma-js" })); + const safeList = new Map(Object.entries({ jquery: "jquery", chroma: "chroma-js" })); const host = createServerHost([app, jquery, chroma]); const logger = trackingLogger(); @@ -1594,7 +1594,7 @@ describe("unittests:: tsserver:: typingsInstaller:: discover typings", () => { content: "" }; const host = createServerHost([f, node]); - const cache = new Map(ts.getEntries({ node: { typingLocation: node.path, version: new ts.Version("1.3.0") } })); + const cache = new Map(Object.entries({ node: { typingLocation: node.path, version: new ts.Version("1.3.0") } })); const registry = createTypesRegistry("node"); const logger = trackingLogger(); const result = ts.JsTyping.discoverTypings(host, logger.log, [f.path], ts.getDirectoryPath(f.path as ts.Path), emptySafeList, cache, { enable: true }, ["fs", "bar"], registry, ts.emptyOptions); @@ -1616,7 +1616,7 @@ describe("unittests:: tsserver:: typingsInstaller:: discover typings", () => { content: "" }; const host = createServerHost([f, node]); - const cache = new Map(ts.getEntries({ node: { typingLocation: node.path, version: new ts.Version("1.3.0") } })); + const cache = new Map(Object.entries({ node: { typingLocation: node.path, version: new ts.Version("1.3.0") } })); const logger = trackingLogger(); const result = ts.JsTyping.discoverTypings(host, logger.log, [f.path], ts.getDirectoryPath(f.path as ts.Path), emptySafeList, cache, { enable: true }, ["fs", "bar"], ts.emptyMap, ts.emptyOptions); assert.deepEqual(logger.finish(), [ @@ -1697,7 +1697,7 @@ describe("unittests:: tsserver:: typingsInstaller:: discover typings", () => { content: "export let y: number" }; const host = createServerHost([app]); - const cache = new Map(ts.getEntries({ + const cache = new Map(Object.entries({ node: { typingLocation: node.path, version: new ts.Version("1.3.0") }, commander: { typingLocation: commander.path, version: new ts.Version("1.0.0") } })); @@ -1723,7 +1723,7 @@ describe("unittests:: tsserver:: typingsInstaller:: discover typings", () => { content: "export let y: number" }; const host = createServerHost([app]); - const cache = new Map(ts.getEntries({ + const cache = new Map(Object.entries({ node: { typingLocation: node.path, version: new ts.Version("1.0.0") } })); const registry = createTypesRegistry("node"); @@ -1754,7 +1754,7 @@ describe("unittests:: tsserver:: typingsInstaller:: discover typings", () => { content: "export let y: number" }; const host = createServerHost([app]); - const cache = new Map(ts.getEntries({ + const cache = new Map(Object.entries({ node: { typingLocation: node.path, version: new ts.Version("1.3.0-next.0") }, commander: { typingLocation: commander.path, version: new ts.Version("1.3.0-next.0") } })); diff --git a/src/tsserver/nodeServer.ts b/src/tsserver/nodeServer.ts index 29ed8aaa81109..3939e508dfd5b 100644 --- a/src/tsserver/nodeServer.ts +++ b/src/tsserver/nodeServer.ts @@ -55,7 +55,6 @@ import { DirectoryWatcherCallback, FileWatcher, getDirectoryPath, - getEntries, getNodeMajorVersion, getRootLength, JsTyping, @@ -691,7 +690,7 @@ function startNodeSession(options: StartSessionOptions, logger: Logger, cancella switch (response.kind) { case EventTypesRegistry: - this.typesRegistryCache = new Map(getEntries(response.typesRegistry)); + this.typesRegistryCache = new Map(Object.entries(response.typesRegistry)); break; case ActionPackageInstalled: { const { success, message } = response; diff --git a/src/typingsInstaller/nodeTypingsInstaller.ts b/src/typingsInstaller/nodeTypingsInstaller.ts index 0d8d0eb5d61aa..032fdb6a98b03 100644 --- a/src/typingsInstaller/nodeTypingsInstaller.ts +++ b/src/typingsInstaller/nodeTypingsInstaller.ts @@ -27,7 +27,6 @@ import { Debug, forEachAncestorDirectory, getDirectoryPath, - getEntries, MapLike, normalizePath, normalizeSlashes, @@ -83,7 +82,7 @@ function loadTypesRegistryFile(typesRegistryFilePath: string, host: InstallTypin } try { const content = JSON.parse(host.readFile(typesRegistryFilePath)!) as TypesRegistryFile; - return new Map(getEntries(content.entries)); + return new Map(Object.entries(content.entries)); } catch (e) { if (log.isEnabled()) { From a21843e6ce85fd0fe52b5a14105014fea22dc6b8 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 15 Dec 2022 19:52:54 -0800 Subject: [PATCH 04/22] Remove arrayFrom --- src/compiler/builder.ts | 17 ++- src/compiler/builderState.ts | 9 +- src/compiler/checker.ts | 33 +++-- src/compiler/commandLineParser.ts | 15 +-- src/compiler/core.ts | 127 ++++-------------- src/compiler/corePublic.ts | 2 +- src/compiler/moduleNameResolver.ts | 3 +- src/compiler/moduleSpecifiers.ts | 3 +- src/compiler/program.ts | 3 +- src/compiler/sourcemap.ts | 8 +- src/compiler/transformers/declarations.ts | 5 +- src/compiler/transformers/jsx.ts | 7 +- src/compiler/utilities.ts | 3 +- src/executeCommandLine/executeCommandLine.ts | 7 +- src/harness/fourslashImpl.ts | 10 +- src/harness/harnessIO.ts | 4 +- src/harness/vfsUtil.ts | 3 +- src/server/editorServices.ts | 34 ++--- src/server/project.ts | 9 +- src/server/session.ts | 13 +- src/services/codeFixProvider.ts | 3 +- src/services/codefixes/convertToEsModule.ts | 5 +- src/services/codefixes/fixAddMissingMember.ts | 7 +- src/services/codefixes/helpers.ts | 7 +- src/services/codefixes/importFixes.ts | 8 +- src/services/documentHighlights.ts | 6 +- src/services/documentRegistry.ts | 5 +- src/services/refactorProvider.ts | 3 +- src/services/refactors/convertImport.ts | 3 +- src/services/refactors/extractSymbol.ts | 3 +- src/services/stringCompletions.ts | 11 +- src/services/symbolDisplay.ts | 3 +- src/testRunner/unittests/compilerCore.ts | 6 +- src/testRunner/unittests/customTransforms.ts | 5 +- src/testRunner/unittests/programApi.ts | 2 +- src/testRunner/unittests/tsc/helpers.ts | 5 +- .../unittests/tscWatch/incremental.ts | 4 +- .../tsserver/cachingFileSystemInformation.ts | 2 +- src/testRunner/unittests/tsserver/helpers.ts | 2 +- .../reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- 41 files changed, 156 insertions(+), 253 deletions(-) diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 550baef382984..1893cbcaeb1df 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -2,7 +2,6 @@ import * as ts from "./_namespaces/ts"; import { addRange, AffectedFileResult, - arrayFrom, arrayToMap, BuilderProgram, BuilderProgramHost, @@ -968,7 +967,7 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde if (outFile(state.compilerOptions)) { // Copy all fileInfo, version and impliedFormat // Affects global scope and signature doesnt matter because with --out they arent calculated or needed to determine upto date ness - const fileInfos = arrayFrom(state.fileInfos.entries(), ([key, value]): ProgramBundleEmitBuildInfoFileInfo => { + const fileInfos = Array.from(state.fileInfos.entries(), ([key, value]): ProgramBundleEmitBuildInfoFileInfo => { // Ensure fileId toFileId(key); return value.impliedFormat ? @@ -1001,7 +1000,7 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde let fileIdsList: (readonly ProgramBuildInfoFileId[])[] | undefined; let fileNamesToFileIdListId: Map | undefined; let emitSignatures: ProgramBuildInfoEmitSignature[] | undefined; - const fileInfos = arrayFrom(state.fileInfos.entries(), ([key, value]): ProgramMultiFileEmitBuildInfoFileInfo => { + const fileInfos = Array.from(state.fileInfos.entries(), ([key, value]): ProgramMultiFileEmitBuildInfoFileInfo => { // Ensure fileId const fileId = toFileId(key); Debug.assert(fileNames[fileId - 1] === relativeToBuildInfo(key)); @@ -1037,7 +1036,7 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde let referencedMap: ProgramBuildInfoReferencedMap | undefined; if (state.referencedMap) { - referencedMap = arrayFrom(state.referencedMap.keys()).sort(compareStringsCaseSensitive).map(key => [ + referencedMap = Array.from(state.referencedMap.keys()).sort(compareStringsCaseSensitive).map(key => [ toFileId(key), toFileIdListId(state.referencedMap!.getValues(key)!) ]); @@ -1045,7 +1044,7 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde let exportedModulesMap: ProgramBuildInfoReferencedMap | undefined; if (state.exportedModulesMap) { - exportedModulesMap = mapDefined(arrayFrom(state.exportedModulesMap.keys()).sort(compareStringsCaseSensitive), key => { + exportedModulesMap = mapDefined(Array.from(state.exportedModulesMap.keys()).sort(compareStringsCaseSensitive), key => { const oldValue = state.oldExportedModulesMap?.get(key); // Not in temporary cache, use existing value if (oldValue === undefined) return [toFileId(key), toFileIdListId(state.exportedModulesMap!.getValues(key)!)]; @@ -1056,7 +1055,7 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde let semanticDiagnosticsPerFile: ProgramBuildInfoDiagnostic[] | undefined; if (state.semanticDiagnosticsPerFile) { - for (const key of arrayFrom(state.semanticDiagnosticsPerFile.keys()).sort(compareStringsCaseSensitive)) { + for (const key of Array.from(state.semanticDiagnosticsPerFile.keys()).sort(compareStringsCaseSensitive)) { const value = state.semanticDiagnosticsPerFile.get(key)!; (semanticDiagnosticsPerFile ||= []).push( value.length ? @@ -1073,7 +1072,7 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde if (state.affectedFilesPendingEmit?.size) { const fullEmitForOptions = getBuilderFileEmit(state.compilerOptions); const seenFiles = new Set(); - for (const path of arrayFrom(state.affectedFilesPendingEmit.keys()).sort(compareStringsCaseSensitive)) { + for (const path of Array.from(state.affectedFilesPendingEmit.keys()).sort(compareStringsCaseSensitive)) { if (tryAddToSet(seenFiles, path)) { const file = state.program!.getSourceFileByPath(path); if (!file || !sourceFileMayBeEmitted(file, state.program!)) continue; @@ -1091,7 +1090,7 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde let changeFileSet: ProgramBuildInfoFileId[] | undefined; if (state.changedFilesSet.size) { - for (const path of arrayFrom(state.changedFilesSet.keys()).sort(compareStringsCaseSensitive)) { + for (const path of Array.from(state.changedFilesSet.keys()).sort(compareStringsCaseSensitive)) { (changeFileSet ||= []).push(toFileId(path)); } } @@ -1129,7 +1128,7 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde } function toFileIdListId(set: ReadonlySet): ProgramBuildInfoFileIdListId { - const fileIds = arrayFrom(set.keys(), toFileId).sort(compareValues); + const fileIds = Array.from(set.keys(), toFileId).sort(compareValues); const key = fileIds.join(); let fileIdListId = fileNamesToFileIdListId?.get(key); if (fileIdListId === undefined) { diff --git a/src/compiler/builderState.ts b/src/compiler/builderState.ts index 870e82f2f2d55..014d14725bd93 100644 --- a/src/compiler/builderState.ts +++ b/src/compiler/builderState.ts @@ -1,5 +1,4 @@ import { - arrayFrom, CancellationToken, computeSignatureWithDiagnostics, CustomTransformers, @@ -108,7 +107,7 @@ export namespace BuilderState { export interface ReadonlyManyToManyPathMap { getKeys(v: Path): ReadonlySet | undefined; getValues(k: Path): ReadonlySet | undefined; - keys(): Iterator; + keys(): IterableIterator; } export interface ManyToManyPathMap extends ReadonlyManyToManyPathMap { @@ -529,7 +528,7 @@ export namespace BuilderState { } } - return arrayFrom(mapDefinedIterator(seenMap.keys(), path => programOfThisState.getSourceFileByPath(path)?.fileName ?? path)); + return Array.from(mapDefinedIterator(seenMap.keys(), path => programOfThisState.getSourceFileByPath(path)?.fileName ?? path)); } /** @@ -548,7 +547,7 @@ export namespace BuilderState { */ export function getReferencedByPaths(state: Readonly, referencedFilePath: Path) { const keys = state.referencedMap!.getKeys(referencedFilePath); - return keys ? arrayFrom(keys.keys()) : []; + return keys ? Array.from(keys.keys()) : []; } /** @@ -660,6 +659,6 @@ export namespace BuilderState { } // Return array of values that needs emit - return arrayFrom(mapDefinedIterator(seenFileNamesMap.values(), value => value)); + return Array.from(mapDefinedIterator(seenFileNamesMap.values(), value => value)); } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 023abb380b747..93a70c76de069 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16,7 +16,6 @@ import { append, appendIfUnique, ArrayBindingPattern, - arrayFrom, arrayIsHomogeneous, ArrayLiteralExpression, arrayOf, @@ -2538,7 +2537,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (mainModule.exports?.get(InternalSymbolName.ExportStar) && moduleAugmentation.symbol.exports?.size) { // We may need to merge the module augmentation's exports into the target symbols of the resolved exports const resolvedExports = getResolvedMembersOrExportsOfSymbol(mainModule, MembersOrExportsResolutionKind.resolvedExports); - for (const [key, value] of arrayFrom(moduleAugmentation.symbol.exports.entries())) { + for (const [key, value] of Array.from(moduleAugmentation.symbol.exports.entries())) { if (resolvedExports.has(key) && !mainModule.exports.has(key)) { mergeSymbol(resolvedExports.get(key)!, value); } @@ -5457,7 +5456,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function createTypeofType() { - return getUnionType(arrayFrom(typeofNEFacts.keys(), getStringLiteralType)); + return getUnionType(Array.from(typeofNEFacts.keys(), getStringLiteralType)); } function createTypeParameter(symbol?: Symbol) { @@ -8617,7 +8616,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getNamespaceMembersForSerialization(symbol: Symbol) { - return !symbol.exports ? [] : filter(arrayFrom(symbol.exports.values()), isNamespaceMember); + return !symbol.exports ? [] : filter(Array.from(symbol.exports.values()), isNamespaceMember); } function isTypeOnlyNamespace(symbol: Symbol) { @@ -12136,7 +12135,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const assignments = symbol.assignmentDeclarationMembers; if (assignments) { - const decls = arrayFrom(assignments.values()); + const decls = Array.from(assignments.values()); for (const member of decls) { const assignmentKind = getAssignmentDeclarationKind(member as BinaryExpression | CallExpression); const isInstanceMember = assignmentKind === AssignmentDeclarationKind.PrototypeProperty @@ -13193,7 +13192,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } - return arrayFrom(props.values()); + return Array.from(props.values()); } function getConstraintOfType(type: InstantiableType | UnionOrIntersectionType): Type | undefined { @@ -13643,7 +13642,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { isUnion && (propSet || checkFlags & CheckFlags.Partial) && checkFlags & (CheckFlags.ContainsPrivate | CheckFlags.ContainsProtected) && - !(propSet && getCommonDeclarationsOfSymbols(arrayFrom(propSet.values()))) + !(propSet && getCommonDeclarationsOfSymbols(propSet.values())) ) { // No property was found, or, in a union, a property has a private or protected declaration in one // constituent, but is missing or has a different declaration in another constituent. @@ -13665,7 +13664,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return singleProp; } } - const props = propSet ? arrayFrom(propSet.values()) : [singleProp]; + const props = propSet ? Array.from(propSet.values()) : [singleProp]; let declarations: Declaration[] | undefined; let firstType: Type | undefined; let nameType: Type | undefined; @@ -13751,7 +13750,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return property; } - function getCommonDeclarationsOfSymbols(symbols: readonly Symbol[]) { + function getCommonDeclarationsOfSymbols(symbols: Iterable) { let commonDeclarations: Set | undefined; for (const symbol of symbols) { if (!symbol.declarations) { @@ -16277,7 +16276,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getIntersectionType(types: readonly Type[], aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[], noSupertypeReduction?: boolean): Type { const typeMembershipMap: Map = new Map(); const includes = addTypesToIntersection(typeMembershipMap, 0 as TypeFlags, types); - const typeSet: Type[] = arrayFrom(typeMembershipMap.values()); + const typeSet: Type[] = Array.from(typeMembershipMap.values()); // An intersection type is considered empty if it contains // the type never, or // more than one unit type or, @@ -21524,7 +21523,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } } - const props = arrayFrom(getUnmatchedProperties(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false)); + const props = Array.from(getUnmatchedProperties(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false)); if (!headMessage || (headMessage.code !== Diagnostics.Class_0_incorrectly_implements_interface_1.code && headMessage.code !== Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass.code)) { shouldSkipElaboration = true; // Retain top-level error for interface implementing issues, otherwise omit it @@ -22985,7 +22984,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } - context.resolvedProperties = arrayFrom(names.values()); + context.resolvedProperties = Array.from(names.values()); } return context.resolvedProperties; } @@ -30999,10 +30998,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { s => symbols.has((s.charAt(0).toUpperCase() + s.slice(1)) as __String) ? createSymbol(SymbolFlags.TypeAlias, s as __String) as Symbol : undefined); - candidates = primitives.concat(arrayFrom(symbols.values())); + candidates = primitives.concat(Array.from(symbols.values())); } else { - candidates = arrayFrom(symbols.values()); + candidates = Array.from(symbols.values()); } return getSpellingSuggestionForName(unescapeLeadingUnderscores(name), candidates, meaning); }); @@ -41872,7 +41871,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - return arrayFrom(seen.values()); + return Array.from(seen.values()); } function checkInheritedPropertiesAreIdentical(type: InterfaceType, typeNode: Node): boolean { @@ -45063,7 +45062,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!importTarget) return false; if (importTarget === file) return false; const exports = getExportsOfModule(file.symbol); - for (const s of arrayFrom(exports.values())) { + for (const s of Array.from(exports.values())) { if (s.mergeId) { const merged = getMergedSymbol(s); if (merged.declarations) { @@ -45306,7 +45305,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { // Otherwise issue top-level error since the files appear very identical in terms of what they contain - const list = arrayFrom(conflictingSymbols.keys()).join(", "); + const list = Array.from(conflictingSymbols.keys()).join(", "); diagnostics.add(addRelatedInfo( createDiagnosticForNode(firstFile, Diagnostics.Definitions_of_the_following_identifiers_conflict_with_those_in_another_file_Colon_0, list), createDiagnosticForNode(secondFile, Diagnostics.Conflicts_are_in_this_file) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 26d2a2c0a7ca7..fba058e04aa07 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1,7 +1,6 @@ import { AlternateModeDiagnostics, append, - arrayFrom, ArrayLiteralExpression, arrayToMap, assign, @@ -136,7 +135,7 @@ const jsxOptionMap = new Map(Object.entries({ })); /** @internal */ -export const inverseJsxOptionMap = new Map(arrayFrom(mapIterator(jsxOptionMap.entries(), ([key, value]: [string, JsxEmit]) => ["" + value, key] as const))); +export const inverseJsxOptionMap = new Map(mapIterator(jsxOptionMap.entries(), ([key, value]: [string, JsxEmit]) => ["" + value, key] as const)); // NOTE: The order here is important to default lib ordering as entries will have the same // order in the generated program (see `getDefaultLibPriority` in program.ts). This @@ -1692,7 +1691,7 @@ export function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOpt } function createDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType, createDiagnostic: (message: DiagnosticMessage, arg0: string, arg1: string) => Diagnostic): Diagnostic { - const namesOfType = arrayFrom(opt.type.keys()); + const namesOfType = Array.from(opt.type.keys()); const stringNames = (opt.deprecatedKeys ? namesOfType.filter(k => !opt.deprecatedKeys!.has(k)) : namesOfType).map(key => `'${key}'`).join(", "); return createDiagnostic(Diagnostics.Argument_for_0_option_must_be_Colon_1, `--${opt.name}`, stringNames); } @@ -2598,7 +2597,7 @@ export function convertToTSConfig(configParseResult: ParsedCommandLine, configFi /** @internal */ export function optionMapToObject(optionMap: Map): object { return { - ...arrayFrom(optionMap.entries()).reduce((prev, cur) => ({ ...prev, [cur[0]]: cur[1] }), {}), + ...Array.from(optionMap.entries()).reduce((prev, cur) => ({ ...prev, [cur[0]]: cur[1] }), {}), }; } @@ -3211,7 +3210,7 @@ function parseConfig( if (!ownConfig.raw.exclude && result.exclude) ownConfig.raw.exclude = result.exclude; if (!ownConfig.raw.files && result.files) ownConfig.raw.files = result.files; if (ownConfig.raw.compileOnSave === undefined && result.compileOnSave) ownConfig.raw.compileOnSave = result.compileOnSave; - if (sourceFile && result.extendedSourceFiles) sourceFile.extendedSourceFiles = arrayFrom(result.extendedSourceFiles.keys()); + if (sourceFile && result.extendedSourceFiles) sourceFile.extendedSourceFiles = Array.from(result.extendedSourceFiles.keys()); ownConfig.options = assign(result.options, ownConfig.options); ownConfig.watchOptions = ownConfig.watchOptions && result.watchOptions ? @@ -3739,10 +3738,10 @@ export function getFileNamesFromConfigSpecs( } } - const literalFiles = arrayFrom(literalFileMap.values()); - const wildcardFiles = arrayFrom(wildcardFileMap.values()); + const literalFiles = Array.from(literalFileMap.values()); + const wildcardFiles = Array.from(wildcardFileMap.values()); - return literalFiles.concat(wildcardFiles, arrayFrom(wildCardJsonFileMap.values())); + return literalFiles.concat(wildcardFiles, Array.from(wildCardJsonFileMap.values())); } /** @internal */ diff --git a/src/compiler/core.ts b/src/compiler/core.ts index d70d21792048c..7aabbc3a170fe 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -352,13 +352,10 @@ export function map(array: readonly T[] | undefined, f: (x: T, i: number) /** @internal */ -export function mapIterator(iter: Iterator, mapFn: (x: T) => U): Iterator { - return { - next() { - const iterRes = iter.next(); - return iterRes.done ? iterRes as { done: true, value: never } : { value: mapFn(iterRes.value), done: false }; - } - }; +export function *mapIterator(iter: Iterable, mapFn: (x: T) => U) { + for (const x of iter) { + yield mapFn(x); + } } /** @@ -460,31 +457,11 @@ export function flatMapToMutable(array: readonly T[] | undefined, mapfn: ( } /** @internal */ -export function flatMapIterator(iter: Iterator, mapfn: (x: T) => readonly U[] | Iterator | undefined): Iterator { - const first = iter.next(); - if (first.done) { - return emptyIterator; - } - let currentIter = getIterator(first.value); - return { - next() { - while (true) { - const currentRes = currentIter.next(); - if (!currentRes.done) { - return currentRes; - } - const iterRes = iter.next(); - if (iterRes.done) { - return iterRes as { done: true, value: never }; - } - currentIter = getIterator(iterRes.value); - } - }, - }; - - function getIterator(x: T): Iterator { - const res = mapfn(x); - return res === undefined ? emptyIterator : isArray(res) ? arrayIterator(res) : res; +export function *flatMapIterator(iter: Iterable, mapfn: (x: T) => readonly U[] | Iterable | undefined) { + for (const x of iter) { + const iter2 = mapfn(x); + if (!iter2) continue; + yield* iter2; } } @@ -552,21 +529,13 @@ export function mapDefined(array: readonly T[] | undefined, mapFn: (x: T, } /** @internal */ -export function mapDefinedIterator(iter: Iterator, mapFn: (x: T) => U | undefined): Iterator { - return { - next() { - while (true) { - const res = iter.next(); - if (res.done) { - return res as { done: true, value: never }; - } - const value = mapFn(res.value); - if (value !== undefined) { - return { value, done: false }; - } - } +export function *mapDefinedIterator(iter: Iterable, mapFn: (x: T) => U | undefined) { + for (const x of iter) { + const value = mapFn(x); + if (value !== undefined) { + yield value; } - }; + } } /** @internal */ @@ -613,18 +582,11 @@ export function tryAddToSet(set: Set, value: T) { } /** @internal */ -export const emptyIterator: Iterator = { next: () => ({ value: undefined as never, done: true }) }; +export const emptyIterator: IterableIterator = (function*() {})(); // TODO(jakebailey): remove? empty array? /** @internal */ -export function singleIterator(value: T): Iterator { - let done = false; - return { - next() { - const wasDone = done; - done = true; - return wasDone ? { value: undefined as never, done: true } : { value, done: false }; - } - }; +export function *singleIterator(value: T) { + yield value; } /** @@ -1164,33 +1126,16 @@ export function sort(array: readonly T[], comparer?: Comparer): SortedRead } /** @internal */ -export function arrayIterator(array: readonly T[]): Iterator { - let i = 0; - return { next: () => { - if (i === array.length) { - return { value: undefined as never, done: true }; - } - else { - i++; - return { value: array[i - 1], done: false }; - } - }}; +export function *arrayIterator(array: readonly T[]) { + // TODO(jakebailey): remove? + yield* array; } /** @internal */ -export function arrayReverseIterator(array: readonly T[]): Iterator { - let i = array.length; - return { - next: () => { - if (i === 0) { - return { value: undefined as never, done: true }; - } - else { - i--; - return { value: array[i], done: false }; - } - } - }; +export function *arrayReverseIterator(array: readonly T[]) { + for (let i = array.length - 1; i >= 0; i--) { + yield array[i]; + } } /** @@ -1466,24 +1411,6 @@ export function arrayOf(count: number, f: (index: number) => T): T[] { return result; } -/** - * Shims `Array.from`. - * - * @internal - */ -export function arrayFrom(iterator: Iterator | IterableIterator, map: (t: T) => U): U[]; -/** @internal */ -export function arrayFrom(iterator: Iterator | IterableIterator): T[]; -/** @internal */ -export function arrayFrom(iterator: Iterator | IterableIterator, map?: (t: T) => U): (T | U)[] { - const result: (T | U)[] = []; - for (let iterResult = iterator.next(); !iterResult.done; iterResult = iterator.next()) { - result.push(map ? map(iterResult.value) : iterResult.value); - } - return result; -} - - /** @internal */ export function assign(t: T, ...args: (T | undefined)[]) { for (const arg of args) { @@ -1589,7 +1516,7 @@ export function group(values: readonly T[], getGroupId: (value: T) => string) export function group(values: readonly T[], getGroupId: (value: T) => string, resultSelector: (values: readonly T[]) => R): R[]; /** @internal */ export function group(values: readonly T[], getGroupId: (value: T) => K, resultSelector: (values: readonly T[]) => readonly T[] = identity): readonly (readonly T[])[] { - return arrayFrom(arrayToMultiMap(values, getGroupId).values(), resultSelector); + return Array.from(arrayToMultiMap(values, getGroupId).values(), resultSelector); } /** @internal */ @@ -1876,7 +1803,7 @@ export function createSet(getHashCode: (element: TElem return size; }, forEach(action: (value: TElement, key: TElement, set: Set) => void): void { - for (const elements of arrayFrom(multiMap.values())) { + for (const elements of Array.from(multiMap.values())) { if (isArray(elements)) { for (const element of elements) { action(element, element, set); diff --git a/src/compiler/corePublic.ts b/src/compiler/corePublic.ts index ca36fa2ff4041..de173a1fc04b8 100644 --- a/src/compiler/corePublic.ts +++ b/src/compiler/corePublic.ts @@ -27,7 +27,7 @@ export interface SortedArray extends Array { export interface ReadonlyCollection { readonly size: number; has(key: K): boolean; - keys(): Iterator; + keys(): IterableIterator; } /** Common write methods for ES6 Map/Set. */ diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 4bf80337bf530..7d82a114197b7 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -1,7 +1,6 @@ import { append, appendIfUnique, - arrayFrom, arrayIsEqualTo, changeAnyExtension, CharacterCodes, @@ -923,7 +922,7 @@ function createPackageJsonInfoCache(currentDirectory: string, getCanonicalFileNa } function entries() { const iter = cache?.entries(); - return iter ? arrayFrom(iter) : []; + return iter ? Array.from(iter) : []; } function getInternalMap() { return cache; diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts index 351d98a24bd19..e50da231c6a83 100644 --- a/src/compiler/moduleSpecifiers.ts +++ b/src/compiler/moduleSpecifiers.ts @@ -3,7 +3,6 @@ import { allKeysStartWithDot, AmbientModuleDeclaration, append, - arrayFrom, CharacterCodes, combinePaths, compareBooleans, @@ -646,7 +645,7 @@ function getAllModulePathsWorker(importingFileName: Path, importedFileName: stri directory = newDirectory; } if (allFileNames.size) { - const remainingPaths = arrayFrom(allFileNames.values()); + const remainingPaths = Array.from(allFileNames.values()); if (remainingPaths.length > 1) remainingPaths.sort(comparePathsByRedirectAndNumberOfDirectorySeparators); sortedPaths.push(...remainingPaths); } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index a9ac7f940e220..cfc96686be260 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -4,7 +4,6 @@ import { addEmitFlags, addRange, append, - arrayFrom, arrayIsEqualTo, AsExpression, AssertClause, @@ -1710,7 +1709,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } } - missingFilePaths = arrayFrom(mapDefinedIterator(filesByName.entries(), ([path, file]) => file === undefined ? path as Path : undefined)); + missingFilePaths = Array.from(mapDefinedIterator(filesByName.entries(), ([path, file]) => file === undefined ? path as Path : undefined)); files = stableSort(processingDefaultLibFiles, compareDefaultLibFiles).concat(processingOtherFiles); processingDefaultLibFiles = undefined; processingOtherFiles = undefined; diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index baf87fdd594c6..0a5e707992fed 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -1,5 +1,4 @@ import { - arrayFrom, binarySearchKey, CharacterCodes, combinePaths, @@ -428,7 +427,7 @@ export function tryParseRawSourceMap(text: string) { } /** @internal */ -export interface MappingsDecoder extends Iterator { +export interface MappingsDecoder extends IterableIterator { readonly pos: number; readonly error: string | undefined; readonly state: Required; @@ -522,6 +521,9 @@ export function decodeMappings(mappings: string): MappingsDecoder { } return stopIterating(); + }, + [Symbol.iterator]() { + return this; } }; @@ -721,7 +723,7 @@ export function createDocumentPositionMapper(host: DocumentPositionMapperHost, m function getDecodedMappings() { if (decodedMappings === undefined) { const decoder = decodeMappings(map.mappings); - const mappings = arrayFrom(decoder, processMapping); + const mappings = Array.from(decoder, processMapping); if (decoder.error !== undefined) { if (host.log) { host.log(`Encountered error while decoding sourcemap: ${decoder.error}`); diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index a150c9204659e..1266d0d2d39f7 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -5,7 +5,6 @@ import { AnyImportSyntax, append, ArrayBindingElement, - arrayFrom, AssertClause, BindingElement, BindingName, @@ -573,11 +572,11 @@ export function transformDeclarations(context: TransformationContext) { return updated; function getLibReferences() { - return map(arrayFrom(libs.keys()), lib => ({ fileName: lib, pos: -1, end: -1 })); + return map(Array.from(libs.keys()), lib => ({ fileName: lib, pos: -1, end: -1 })); } function getFileReferencesForUsedTypeReferences() { - return necessaryTypeReferences ? mapDefined(arrayFrom(necessaryTypeReferences.keys()), getFileReferenceForSpecifierModeTuple) : []; + return necessaryTypeReferences ? mapDefined(Array.from(necessaryTypeReferences.keys()), getFileReferenceForSpecifierModeTuple) : []; } function getFileReferenceForSpecifierModeTuple([typeName, mode]: [specifier: string, mode: ResolutionMode]): FileReference | undefined { diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index 2244f815d9983..c6e8ac6193aa5 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -1,6 +1,5 @@ import { addEmitHelpers, - arrayFrom, Bundle, chainBundle, createExpressionForJsxElement, @@ -160,10 +159,10 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B statements = insertStatementAfterCustomPrologue(statements.slice(), factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([currentFileState.filenameDeclaration], NodeFlags.Const))); } if (currentFileState.utilizedImplicitRuntimeImports) { - for (const [importSource, importSpecifiersMap] of arrayFrom(currentFileState.utilizedImplicitRuntimeImports.entries())) { + for (const [importSource, importSpecifiersMap] of Array.from(currentFileState.utilizedImplicitRuntimeImports.entries())) { if (isExternalModule(node)) { // Add `import` statement - const importStatement = factory.createImportDeclaration(/*modifiers*/ undefined, factory.createImportClause(/*typeOnly*/ false, /*name*/ undefined, factory.createNamedImports(arrayFrom(importSpecifiersMap.values()))), factory.createStringLiteral(importSource), /*assertClause*/ undefined); + const importStatement = factory.createImportDeclaration(/*modifiers*/ undefined, factory.createImportClause(/*typeOnly*/ false, /*name*/ undefined, factory.createNamedImports(Array.from(importSpecifiersMap.values()))), factory.createStringLiteral(importSource), /*assertClause*/ undefined); setParentRecursive(importStatement, /*incremental*/ false); statements = insertStatementAfterCustomPrologue(statements.slice(), importStatement); } @@ -171,7 +170,7 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B // Add `require` statement const requireStatement = factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([ factory.createVariableDeclaration( - factory.createObjectBindingPattern(map(arrayFrom(importSpecifiersMap.values()), s => factory.createBindingElement(/*dotdotdot*/ undefined, s.propertyName, s.name))), + factory.createObjectBindingPattern(Array.from(importSpecifiersMap.values(), s => factory.createBindingElement(/*dotdotdot*/ undefined, s.propertyName, s.name))), /*exclaimationToken*/ undefined, /*type*/ undefined, factory.createCallExpression(factory.createIdentifier("require"), /*typeArguments*/ undefined, [factory.createStringLiteral(importSource)]) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 4fbb9a2aa40be..94ef86cc58fe2 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -12,7 +12,6 @@ import { AnyImportSyntax, AnyValidImportOrReExport, append, - arrayFrom, ArrayLiteralExpression, ArrayTypeNode, ArrowFunction, @@ -1052,7 +1051,7 @@ export function createCommentDirectivesMap(sourceFile: SourceFile, commentDirect return { getUnusedExpectations, markUsed }; function getUnusedExpectations() { - return arrayFrom(directivesByLine.entries()) + return Array.from(directivesByLine.entries()) .filter(([line, directive]) => directive.type === CommentDirectiveType.ExpectError && !usedLines.get(line)) .map(([_, directive]) => directive); } diff --git a/src/executeCommandLine/executeCommandLine.ts b/src/executeCommandLine/executeCommandLine.ts index e9a34c4dd4983..9ee87060e48db 100644 --- a/src/executeCommandLine/executeCommandLine.ts +++ b/src/executeCommandLine/executeCommandLine.ts @@ -1,6 +1,5 @@ import * as ts from "./_namespaces/ts"; import { - arrayFrom, BuilderProgram, BuildOptions, buildOpts, @@ -303,7 +302,7 @@ function generateOptionOutput(sys: System, option: CommandLineOption, rightAlign ) { return defaultValue !== undefined && typeof type === "object" // e.g. ScriptTarget.ES2015 -> "es6/es2015" - ? arrayFrom(type.entries()) + ? Array.from(type.entries()) .filter(([, value]) => value === defaultValue) .map(([name]) => name) .join("/") @@ -1158,8 +1157,8 @@ function reportStatistics(sys: System, programOrConfig: Program | ParsedCommandL const lineCounts = countLines(program); if (compilerOptions.extendedDiagnostics) { - for (const key of arrayFrom(lineCounts.keys())) { - reportCountStatistic("Lines of " + key, lineCounts.get(key)!); + for (const [key, value] of lineCounts.entries()) { + reportCountStatistic("Lines of " + key, value); } } else { diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 63b6a25a9c5d9..6eb77d724b12d 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -1954,7 +1954,7 @@ export class TestState { public baselineQuickInfo() { const baselineFile = this.getBaselineFileNameForContainingTestFile(); - const result = ts.arrayFrom(this.testData.markerPositions.entries(), ([name, marker]) => ({ + const result = Array.from(this.testData.markerPositions.entries(), ([name, marker]) => ({ marker: { ...marker, name }, quickInfo: this.languageService.getQuickInfoAtPosition(marker.fileName, marker.position) })); @@ -1963,7 +1963,7 @@ export class TestState { public baselineSignatureHelp() { const baselineFile = this.getBaselineFileNameForContainingTestFile(); - const result = ts.arrayFrom(this.testData.markerPositions.entries(), ([name, marker]) => ({ + const result = Array.from(this.testData.markerPositions.entries(), ([name, marker]) => ({ marker: { ...marker, name }, signatureHelp: this.languageService.getSignatureHelpItems(marker.fileName, marker.position, /*options*/ undefined) })); @@ -1972,7 +1972,7 @@ export class TestState { public baselineCompletions(preferences?: ts.UserPreferences) { const baselineFile = this.getBaselineFileNameForContainingTestFile(); - const result = ts.arrayFrom(this.testData.markerPositions.entries(), ([name, marker]) => { + const result = Array.from(this.testData.markerPositions.entries(), ([name, marker]) => { this.goToMarker(marker); const completions = this.getCompletionListAtCaret(preferences); return { @@ -2515,7 +2515,7 @@ export class TestState { } public getMarkerNames(): string[] { - return ts.arrayFrom(this.testData.markerPositions.keys()); + return Array.from(this.testData.markerPositions.keys()); } public getRanges(): Range[] { @@ -4587,7 +4587,7 @@ function unique(inputs: readonly T[], getOutput: (t: T) => string): string[] const out = getOutput(input); set.set(out, true); } - return ts.arrayFrom(set.keys()); + return Array.from(set.keys()); } function toArray(x: ArrayOrSingle): readonly T[] { diff --git a/src/harness/harnessIO.ts b/src/harness/harnessIO.ts index 99ed2db1136c9..89909e80693ba 100644 --- a/src/harness/harnessIO.ts +++ b/src/harness/harnessIO.ts @@ -1048,7 +1048,7 @@ function splitVaryBySettingValue(text: string, varyBy: string): string[] | undef if (star && values) { // add all entries - for (const [key, value] of ts.arrayFrom(values.entries())) { + for (const [key, value] of Array.from(values.entries())) { if (ts.findIndex(variations, v => v.key === key || v.value === value) === -1) { variations.push({ key, value }); } @@ -1482,7 +1482,7 @@ export namespace Baseline { errorMsg += "\n"; } if (missing.length) { - const writtenFilesArray = ts.arrayFrom(writtenFiles.keys()); + const writtenFilesArray = Array.from(writtenFiles.keys()); errorMsg += `Baseline missing ${missing.length} files:${"\n " + missing.slice(0, 5).join("\n ") + (missing.length > 5 ? "\n" + ` and ${missing.length - 5} more` : "") + "\n"}Written ${writtenFiles.size} files:${"\n " + writtenFilesArray.slice(0, 5).join("\n ") + (writtenFilesArray.length > 5 ? "\n" + ` and ${writtenFilesArray.length - 5} more` : "")}`; } throw new Error(errorMsg); diff --git a/src/harness/vfsUtil.ts b/src/harness/vfsUtil.ts index 4547e378cf368..35adcfb354b2c 100644 --- a/src/harness/vfsUtil.ts +++ b/src/harness/vfsUtil.ts @@ -1626,7 +1626,8 @@ function* iteratePatchWorker(dirname: string, container: FileSet): IterableItera const entry = normalizeFileSetEntry(container[name]); const file = dirname ? vpath.combine(dirname, name) : name; if (entry instanceof Directory) { - yield* ts.arrayFrom(iteratePatchWorker(file, entry.files)); + // TODO(jakebailey): redundant? + yield* Array.from(iteratePatchWorker(file, entry.files)); } else if (entry instanceof File) { const content = typeof entry.data === "string" ? entry.data : entry.data.toString("utf8"); diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 8762170c10d79..f983a660203c6 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -48,7 +48,7 @@ import { } from "./_namespaces/ts.server"; import { addToSeen, - arrayFrom, + arrayToMap, AssertionLevel, CachedDirectoryStructureHost, @@ -1211,7 +1211,7 @@ export class ProjectService { const event: ProjectsUpdatedInBackgroundEvent = { eventName: ProjectsUpdatedInBackgroundEvent, data: { - openFiles: arrayFrom(this.openFiles.keys(), path => this.getScriptInfoForPath(path as Path)!.fileName) + openFiles: Array.from(this.openFiles.keys(), path => this.getScriptInfoForPath(path as Path)!.fileName) } }; this.eventHandler(event); @@ -1642,7 +1642,7 @@ export class ProjectService { !info.isAttached(project), "Found script Info still attached to project", () => `${project.projectName}: ScriptInfos still attached: ${JSON.stringify( - arrayFrom( + Array.from( mapDefinedIterator( this.filenameToScriptInfo.values(), info => info.isAttached(project) ? @@ -2782,7 +2782,7 @@ export class ProjectService { /** @internal */ logErrorForScriptInfoNotFound(fileName: string): void { - const names = arrayFrom(this.filenameToScriptInfo.entries()).map(([path, scriptInfo]) => ({ path, fileName: scriptInfo.fileName })); + const names = Array.from(this.filenameToScriptInfo.entries(), ([path, scriptInfo]) => ({ path, fileName: scriptInfo.fileName })); this.logger.msg(`Could not find file ${JSON.stringify(fileName)}.\nAll files are: ${JSON.stringify(names)}`, Msg.Err); } @@ -2990,9 +2990,9 @@ export class ProjectService { let info = this.getScriptInfoForPath(path); if (!info) { const isDynamic = isDynamicFileName(fileName); - Debug.assert(isRootedDiskPath(fileName) || isDynamic || openedByClient, "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: arrayFrom(this.openFilesWithNonRootedDiskPath.keys()) })}\nScript info with non-dynamic relative file name can only be open script info or in context of host currentDirectory`); - Debug.assert(!isRootedDiskPath(fileName) || this.currentDirectory === currentDirectory || !this.openFilesWithNonRootedDiskPath.has(this.toCanonicalFileName(fileName)), "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: arrayFrom(this.openFilesWithNonRootedDiskPath.keys()) })}\nOpen script files with non rooted disk path opened with current directory context cannot have same canonical names`); - Debug.assert(!isDynamic || this.currentDirectory === currentDirectory || this.useInferredProjectPerProjectRoot, "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: arrayFrom(this.openFilesWithNonRootedDiskPath.keys()) })}\nDynamic files must always be opened with service's current directory or service should support inferred project per projectRootPath.`); + Debug.assert(isRootedDiskPath(fileName) || isDynamic || openedByClient, "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: Array.from(this.openFilesWithNonRootedDiskPath.keys()) })}\nScript info with non-dynamic relative file name can only be open script info or in context of host currentDirectory`); + Debug.assert(!isRootedDiskPath(fileName) || this.currentDirectory === currentDirectory || !this.openFilesWithNonRootedDiskPath.has(this.toCanonicalFileName(fileName)), "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: Array.from(this.openFilesWithNonRootedDiskPath.keys()) })}\nOpen script files with non rooted disk path opened with current directory context cannot have same canonical names`); + Debug.assert(!isDynamic || this.currentDirectory === currentDirectory || this.useInferredProjectPerProjectRoot, "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: Array.from(this.openFilesWithNonRootedDiskPath.keys()) })}\nDynamic files must always be opened with service's current directory or service should support inferred project per projectRootPath.`); // If the file is not opened by client and the file doesnot exist on the disk, return if (!openedByClient && !isDynamic && !(hostToQueryFileExistsOn || this.host).fileExists(fileName)) { return; @@ -3675,7 +3675,7 @@ export class ProjectService { const seenProjects = new Set(); // Work on array copy as we could add more projects as part of callback - for (const project of arrayFrom(this.configuredProjects.values())) { + for (const project of Array.from(this.configuredProjects.values())) { // If this project has potential project reference for any of the project we are loading ancestor tree for // load this project first if (forEachPotentialProjectReference(project, potentialRefPath => forProjects!.has(potentialRefPath))) { @@ -3878,7 +3878,7 @@ export class ProjectService { private collectChanges( lastKnownProjectVersions: protocol.ProjectVersionInfo[], - currentProjects: Project[], + currentProjects: Iterable, includeProjectReferenceRedirectInfo: boolean | undefined, result: ProjectFilesWithTSDiagnostics[] ): void { @@ -3892,20 +3892,17 @@ export class ProjectService { synchronizeProjectList(knownProjects: protocol.ProjectVersionInfo[], includeProjectReferenceRedirectInfo?: boolean): ProjectFilesWithTSDiagnostics[] { const files: ProjectFilesWithTSDiagnostics[] = []; this.collectChanges(knownProjects, this.externalProjects, includeProjectReferenceRedirectInfo, files); - this.collectChanges(knownProjects, arrayFrom(this.configuredProjects.values()), includeProjectReferenceRedirectInfo, files); + this.collectChanges(knownProjects, this.configuredProjects.values(), includeProjectReferenceRedirectInfo, files); this.collectChanges(knownProjects, this.inferredProjects, includeProjectReferenceRedirectInfo, files); return files; } /** @internal */ - applyChangesInOpenFiles(openFiles: Iterator | undefined, changedFiles?: Iterator, closedFiles?: string[]): void { + applyChangesInOpenFiles(openFiles: Iterable | undefined, changedFiles?: Iterable, closedFiles?: string[]): void { let openScriptInfos: ScriptInfo[] | undefined; let assignOrphanScriptInfosToInferredProject = false; if (openFiles) { - while (true) { - const iterResult = openFiles.next(); - if (iterResult.done) break; - const file = iterResult.value; + for (const file of openFiles) { // Create script infos so we have the new content for all the open files before we do any updates to projects const info = this.getOrCreateOpenScriptInfo( toNormalizedPath(file.fileName), @@ -3919,10 +3916,7 @@ export class ProjectService { } if (changedFiles) { - while (true) { - const iterResult = changedFiles.next(); - if (iterResult.done) break; - const file = iterResult.value; + for (const file of changedFiles) { const scriptInfo = this.getScriptInfo(file.fileName)!; Debug.assert(!!scriptInfo); // Make edits to script infos and marks containing project as dirty @@ -4339,7 +4333,7 @@ export class ProjectService { } // Consume the pending plugin enablement requests - const entries = arrayFrom(this.pendingPluginEnablements.entries()); + const entries = Array.from(this.pendingPluginEnablements.entries()); this.pendingPluginEnablements = undefined; // Start processing the requests, keeping track of the promise for the operation so that diff --git a/src/server/project.ts b/src/server/project.ts index ab2a5252cd749..ec6c88368e824 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -26,7 +26,6 @@ import { addRange, append, ApplyCodeActionCommandResult, - arrayFrom, arrayToMap, BuilderState, CachedDirectoryStructureHost, @@ -1655,11 +1654,11 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo getChangesSinceVersion(lastKnownVersion?: number, includeProjectReferenceRedirectInfo?: boolean): ProjectFilesWithTSDiagnostics { const includeProjectReferenceRedirectInfoIfRequested = includeProjectReferenceRedirectInfo - ? (files: Map) => arrayFrom(files.entries(), ([fileName, isSourceOfProjectReferenceRedirect]): protocol.FileWithProjectReferenceRedirectInfo => ({ + ? (files: Map) => Array.from(files.entries(), ([fileName, isSourceOfProjectReferenceRedirect]): protocol.FileWithProjectReferenceRedirectInfo => ({ fileName, isSourceOfProjectReferenceRedirect })) - : (files: Map) => arrayFrom(files.keys()); + : (files: Map) => Array.from(files.keys()); // Update the graph only if initial configured project load is not pending if (!this.isInitialLoadPending()) { @@ -1697,7 +1696,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo const added: Map = new Map(); const removed: Map = new Map(); - const updated: string[] = updatedFileNames ? arrayFrom(updatedFileNames.keys()) : []; + const updated: string[] = updatedFileNames ? Array.from(updatedFileNames.keys()) : []; const updatedRedirects: protocol.FileWithProjectReferenceRedirectInfo[] = []; forEachEntry(currentFiles, (isSourceOfProjectReferenceRedirect, fileName) => { @@ -2280,7 +2279,7 @@ export class AutoImportProviderProject extends Project { let dependenciesAdded = 0; if (dependencyNames) { const symlinkCache = hostProject.getSymlinkCache(); - for (const name of arrayFrom(dependencyNames.keys())) { + for (const name of Array.from(dependencyNames.keys())) { // Avoid creating a large project that would significantly slow down time to editor interactivity if (dependencySelection === PackageJsonAutoImportPreference.Auto && dependenciesAdded > this.maxDependencies) { hostProject.log(`AutoImportProviderProject: attempted to add more than ${this.maxDependencies} dependencies. Aborting.`); diff --git a/src/server/session.ts b/src/server/session.ts index 16324cdac26f3..0104c304d3db6 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1,5 +1,4 @@ import { - arrayFrom, arrayIterator, arrayReverseIterator, CallHierarchyIncomingCall, @@ -1341,7 +1340,7 @@ export class Session implements EventSender { private cleanup() { this.cleanProjects("inferred projects", this.projectService.inferredProjects); - this.cleanProjects("configured projects", arrayFrom(this.projectService.configuredProjects.values())); + this.cleanProjects("configured projects", Array.from(this.projectService.configuredProjects.values())); this.cleanProjects("external projects", this.projectService.externalProjects); if (this.host.gc) { this.logger.info(`host.gc()`); @@ -1545,7 +1544,7 @@ export class Session implements EventSender { } } } - definitions = arrayFrom(definitionSet.values()); + definitions = Array.from(definitionSet.values()); } definitions = definitions.filter(d => !d.isAmbient && !d.failedAliasResolution); @@ -1969,7 +1968,7 @@ export class Session implements EventSender { const scriptInfo = Debug.checkDefined(this.projectService.getScriptInfo(fileName)); group.locs.push({ ...toProtocolTextSpanWithContext(textSpan, contextSpan, scriptInfo), ...prefixSuffixText }); } - return arrayFrom(map.values()); + return Array.from(map.values()); } private getReferences(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.ReferencesResponseBody | readonly ReferencedSymbol[] { @@ -3142,13 +3141,13 @@ export class Session implements EventSender { [CommandNames.UpdateOpen]: (request: protocol.UpdateOpenRequest) => { this.changeSeq++; this.projectService.applyChangesInOpenFiles( - request.arguments.openFiles && mapIterator(arrayIterator(request.arguments.openFiles), file => ({ + request.arguments.openFiles && mapIterator(request.arguments.openFiles, file => ({ fileName: file.file, content: file.fileContent, scriptKind: file.scriptKindName, projectRootPath: file.projectRootPath })), - request.arguments.changedFiles && mapIterator(arrayIterator(request.arguments.changedFiles), file => ({ + request.arguments.changedFiles && mapIterator(request.arguments.changedFiles, file => ({ fileName: file.fileName, changes: mapDefinedIterator(arrayReverseIterator(file.textChanges), change => { const scriptInfo = Debug.checkDefined(this.projectService.getScriptInfo(file.fileName)); @@ -3164,7 +3163,7 @@ export class Session implements EventSender { [CommandNames.ApplyChangedToOpenFiles]: (request: protocol.ApplyChangedToOpenFilesRequest) => { this.changeSeq++; this.projectService.applyChangesInOpenFiles( - request.arguments.openFiles && arrayIterator(request.arguments.openFiles), + request.arguments.openFiles, request.arguments.changedFiles && mapIterator(arrayIterator(request.arguments.changedFiles), file => ({ fileName: file.fileName, // apply changes in reverse order diff --git a/src/services/codeFixProvider.ts b/src/services/codeFixProvider.ts index de923d7242433..4a8ff6d1bc057 100644 --- a/src/services/codeFixProvider.ts +++ b/src/services/codeFixProvider.ts @@ -1,5 +1,4 @@ import { - arrayFrom, cast, CodeActionCommand, CodeFixAction, @@ -62,7 +61,7 @@ export function registerCodeFix(reg: CodeFixRegistration) { /** @internal */ export function getSupportedErrorCodes(): readonly string[] { - return arrayFrom(errorCodeToFixes.keys()); + return Array.from(errorCodeToFixes.keys()); } function removeFixIdIfFixAllUnavailable(registration: CodeFixRegistration, diagnostics: Diagnostic[]) { diff --git a/src/services/codefixes/convertToEsModule.ts b/src/services/codefixes/convertToEsModule.ts index 959b9ea4538ad..ed38f5f58c4c5 100644 --- a/src/services/codefixes/convertToEsModule.ts +++ b/src/services/codefixes/convertToEsModule.ts @@ -5,7 +5,6 @@ import { } from "../_namespaces/ts.codefix"; import { __String, - arrayFrom, ArrowFunction, BinaryExpression, BindingElement, @@ -453,7 +452,7 @@ function convertExportsDotXEquals_replaceNode(name: string | undefined, exported function replaceImportUseSites(node: T, useSitesToUnqualify: Map | undefined): T; function replaceImportUseSites(nodes: NodeArray, useSitesToUnqualify: Map | undefined): NodeArray; function replaceImportUseSites(nodeOrNodes: T | NodeArray, useSitesToUnqualify: Map | undefined) { - if (!useSitesToUnqualify || !some(arrayFrom(useSitesToUnqualify.keys()), original => rangeContainsRange(nodeOrNodes, original))) { + if (!useSitesToUnqualify || !some(Array.from(useSitesToUnqualify.keys()), original => rangeContainsRange(nodeOrNodes, original))) { return nodeOrNodes; } @@ -559,7 +558,7 @@ function convertSingleIdentifierImport(name: Identifier, moduleSpecifier: String } } - const namedBindings = namedBindingsNames.size === 0 ? undefined : arrayFrom(mapIterator(namedBindingsNames.entries(), ([propertyName, idName]) => + const namedBindings = namedBindingsNames.size === 0 ? undefined : Array.from(mapIterator(namedBindingsNames.entries(), ([propertyName, idName]) => factory.createImportSpecifier(/*isTypeOnly*/ false, propertyName === idName ? undefined : factory.createIdentifier(propertyName), factory.createIdentifier(idName)))); if (!namedBindings) { // If it was unused, ensure that we at least import *something*. diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index 80fdb0380ad1c..3b7a05a742787 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -1,7 +1,6 @@ import { __String, addToSeen, - arrayFrom, BigIntLiteralType, BinaryExpression, CallExpression, @@ -308,7 +307,7 @@ function getInfo(sourceFile: SourceFile, tokenPos: number, errorCode: number, ch const param = signature.parameters[argIndex].valueDeclaration; if (!(param && isParameter(param) && isIdentifier(param.name))) return undefined; - const properties = arrayFrom(checker.getUnmatchedProperties(checker.getTypeAtLocation(parent), checker.getParameterType(signature, argIndex), /* requireOptionalProperties */ false, /* matchDiscriminantProperties */ false)); + const properties = Array.from(checker.getUnmatchedProperties(checker.getTypeAtLocation(parent), checker.getParameterType(signature, argIndex), /* requireOptionalProperties */ false, /* matchDiscriminantProperties */ false)); if (!length(properties)) return undefined; return { kind: InfoKind.ObjectLiteral, token: param.name, properties, parentDeclaration: parent }; } @@ -316,7 +315,7 @@ function getInfo(sourceFile: SourceFile, tokenPos: number, errorCode: number, ch if (!isMemberName(token)) return undefined; if (isIdentifier(token) && hasInitializer(parent) && parent.initializer && isObjectLiteralExpression(parent.initializer)) { - const properties = arrayFrom(checker.getUnmatchedProperties(checker.getTypeAtLocation(parent.initializer), checker.getTypeAtLocation(token), /* requireOptionalProperties */ false, /* matchDiscriminantProperties */ false)); + const properties = Array.from(checker.getUnmatchedProperties(checker.getTypeAtLocation(parent.initializer), checker.getTypeAtLocation(token), /* requireOptionalProperties */ false, /* matchDiscriminantProperties */ false)); if (!length(properties)) return undefined; return { kind: InfoKind.ObjectLiteral, token, properties, parentDeclaration: parent.initializer }; @@ -665,7 +664,7 @@ function tryGetValueFromType(context: CodeFixContextBase, checker: TypeChecker, return factory.createFalse(); } if (type.flags & TypeFlags.EnumLike) { - const enumMember = type.symbol.exports ? firstOrUndefined(arrayFrom(type.symbol.exports.values())) : type.symbol; + const enumMember = type.symbol.exports ? firstOrUndefined(Array.from(type.symbol.exports.values())) : type.symbol; const name = checker.symbolToExpression(type.symbol.parent ? type.symbol.parent : type.symbol, SymbolFlags.Value, /*enclosingDeclaration*/ undefined, /*flags*/ undefined); return enumMember === undefined || name === undefined ? factory.createNumericLiteral(0) : factory.createPropertyAccessExpression(name, checker.symbolToString(enumMember)); } diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index 8f85058cc6334..ca3713c6a4260 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -1,7 +1,6 @@ import { AccessorDeclaration, append, - arrayFrom, ArrowFunction, Block, CallExpression, @@ -522,8 +521,8 @@ function createTypeParametersForArguments(checker: TypeChecker, argumentTypePara } } - return map( - arrayFrom(usedNames.values()), + return Array.from( + usedNames.values(), usedName => factory.createTypeParameterDeclaration(/*modifiers*/ undefined, usedName, constraintsByName.get(usedName)?.constraint), ); } @@ -627,7 +626,7 @@ export function getArgumentTypesAndTypeParameters(checker: TypeChecker, importAd } } - return { argumentTypeNodes, argumentTypeParameters: arrayFrom(argumentTypeParameters.entries()) }; + return { argumentTypeNodes, argumentTypeParameters: Array.from(argumentTypeParameters.entries()) }; } function isAnonymousObjectConstraintType(type: Type) { diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index ac89579ab0ed5..51e2bb8db39ae 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -2,7 +2,6 @@ import { AnyImportOrRequire, AnyImportOrRequireStatement, AnyImportSyntax, - arrayFrom, CancellationToken, cast, CodeAction, @@ -357,7 +356,7 @@ function createImportAdderWorker(sourceFile: SourceFile, program: Program, useAu sourceFile, importClauseOrBindingPattern, defaultImport, - arrayFrom(namedImports.entries(), ([name, addAsTypeOnly]) => ({ addAsTypeOnly, name })), + Array.from(namedImports.entries(), ([name, addAsTypeOnly]) => ({ addAsTypeOnly, name })), compilerOptions, preferences); }); @@ -370,7 +369,7 @@ function createImportAdderWorker(sourceFile: SourceFile, program: Program, useAu moduleSpecifier, quotePreference, defaultImport, - namedImports && arrayFrom(namedImports.entries(), ([name, addAsTypeOnly]) => ({ addAsTypeOnly, name })), + namedImports && Array.from(namedImports.entries(), ([name, addAsTypeOnly]) => ({ addAsTypeOnly, name })), namespaceLikeImport); newDeclarations = combine(newDeclarations, declarations); }); @@ -1066,7 +1065,8 @@ function getFixesInfoForNonUMDImport({ sourceFile, program, cancellationToken, h const isValidTypeOnlyUseSite = isValidTypeOnlyAliasUseSite(symbolToken); const useRequire = shouldUseRequire(sourceFile, program); const exportInfo = getExportInfos(symbolName, isJSXTagName(symbolToken), getMeaningFromLocation(symbolToken), cancellationToken, sourceFile, program, useAutoImportProvider, host, preferences); - const fixes = arrayFrom(flatMapIterator(exportInfo.entries(), ([_, exportInfos]) => + // TODO(jakebailey): surely this doesn't need the intermediary array + const fixes = Array.from(flatMapIterator(exportInfo.entries(), ([_, exportInfos]) => getImportFixes(exportInfos, { symbolName, position: symbolToken.getStart(sourceFile) }, isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences).fixes)); return fixes.map(fix => ({ fix, symbolName, errorIdentifierText: symbolToken.text, isJsxNamespaceFix: symbolName !== symbolToken.text })); }); diff --git a/src/services/documentHighlights.ts b/src/services/documentHighlights.ts index 797d7346b36c7..52c7e1e0de1bf 100644 --- a/src/services/documentHighlights.ts +++ b/src/services/documentHighlights.ts @@ -1,6 +1,5 @@ import { __String, - arrayFrom, arrayToMultiMap, Block, BreakOrContinueStatement, @@ -62,6 +61,7 @@ import { isYieldExpression, IterationStatement, mapDefined, + mapDefinedIterator, MethodDeclaration, Modifier, ModifierFlags, @@ -117,7 +117,7 @@ export namespace DocumentHighlights { if (!referenceEntries) return undefined; const map = arrayToMultiMap(referenceEntries.map(FindAllReferences.toHighlightSpan), e => e.fileName, e => e.span); const getCanonicalFileName = createGetCanonicalFileName(program.useCaseSensitiveFileNames()); - return mapDefined(arrayFrom(map.entries()), ([fileName, highlightSpans]) => { + return Array.from(mapDefinedIterator(map.entries(), ([fileName, highlightSpans]) => { if (!sourceFilesSet.has(fileName)) { if (!program.redirectTargetsMap.has(toPath(fileName, program.getCurrentDirectory(), getCanonicalFileName))) { return undefined; @@ -128,7 +128,7 @@ export namespace DocumentHighlights { Debug.assert(sourceFilesSet.has(fileName)); } return { fileName, highlightSpans }; - }); + })); } function getSyntacticDocumentHighlights(node: Node, sourceFile: SourceFile): DocumentHighlights[] | undefined { diff --git a/src/services/documentRegistry.ts b/src/services/documentRegistry.ts index 50f660d6bf746..2c7d5cdda8819 100644 --- a/src/services/documentRegistry.ts +++ b/src/services/documentRegistry.ts @@ -1,5 +1,4 @@ import { - arrayFrom, CompilerOptions, createGetCanonicalFileName, createLanguageServiceSourceFile, @@ -189,7 +188,7 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole const getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames); function reportStats() { - const bucketInfoArray = arrayFrom(buckets.keys()).filter(name => name && name.charAt(0) === "_").map(name => { + const bucketInfoArray = Array.from(buckets.keys()).filter(name => name && name.charAt(0) === "_").map(name => { const entries = buckets.get(name)!; const sourceFiles: { name: string; scriptKind: ScriptKind, refCount: number; }[] = []; entries.forEach((entry, name) => { @@ -384,7 +383,7 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole } function getLanguageServiceRefCounts(path: Path, scriptKind: ScriptKind) { - return arrayFrom(buckets.entries(), ([key, bucket]): [string, number | undefined] => { + return Array.from(buckets.entries(), ([key, bucket]): [string, number | undefined] => { const bucketEntry = bucket.get(path); const entry = bucketEntry && getDocumentRegistryEntry(bucketEntry, scriptKind); return [key, entry && entry.languageServiceRefCount]; diff --git a/src/services/refactorProvider.ts b/src/services/refactorProvider.ts index 611c846c21c99..d452b63eaf7d9 100644 --- a/src/services/refactorProvider.ts +++ b/src/services/refactorProvider.ts @@ -1,6 +1,5 @@ import { ApplicableRefactorInfo, - arrayFrom, flatMapIterator, Refactor, RefactorContext, @@ -23,7 +22,7 @@ export function registerRefactor(name: string, refactor: Refactor) { /** @internal */ export function getApplicableRefactors(context: RefactorContext): ApplicableRefactorInfo[] { - return arrayFrom(flatMapIterator(refactors.values(), refactor => + return Array.from(flatMapIterator(refactors.values(), refactor => context.cancellationToken && context.cancellationToken.isCancellationRequested() || !refactor.kinds?.some(kind => refactorKindBeginsWith(kind, context.kind)) ? undefined : refactor.getAvailableActions(context))); diff --git a/src/services/refactors/convertImport.ts b/src/services/refactors/convertImport.ts index a7d0d0d53123b..7ced03fd64467 100644 --- a/src/services/refactors/convertImport.ts +++ b/src/services/refactors/convertImport.ts @@ -1,6 +1,5 @@ import { ApplicableRefactorInfo, - arrayFrom, codefix, Debug, Diagnostics, @@ -263,7 +262,7 @@ export function doChangeNamedToNamespaceOrDefault(sourceFile: SourceFile, progra ? factory.createIdentifier(namespaceImportName) : factory.createNamespaceImport(factory.createIdentifier(namespaceImportName))); if (neededNamedImports.size) { - const newNamedImports: ImportSpecifier[] = arrayFrom(neededNamedImports.values()).map(element => + const newNamedImports: ImportSpecifier[] = Array.from(neededNamedImports.values(), element => factory.createImportSpecifier(element.isTypeOnly, element.propertyName && factory.createIdentifier(element.propertyName.text), factory.createIdentifier(element.name.text))); changes.insertNodeAfter(sourceFile, toConvert.parent.parent, updateImport(importDecl, /*defaultImportName*/ undefined, newNamedImports)); } diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 35aab0a65c361..e43be41d6a396 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -2,7 +2,6 @@ import { __String, ANONYMOUS, ApplicableRefactorInfo, - arrayFrom, assertType, BindingElement, Block, @@ -1070,7 +1069,7 @@ function extractFunctionInScope( callArguments.push(factory.createIdentifier(name)); }); - const typeParametersAndDeclarations = arrayFrom(typeParameterUsages.values()).map(type => ({ type, declaration: getFirstDeclaration(type) })); + const typeParametersAndDeclarations = Array.from(typeParameterUsages.values(), type => ({ type, declaration: getFirstDeclaration(type) })); const sortedTypeParametersAndDeclarations = typeParametersAndDeclarations.sort(compareTypesByDeclarationOrder); const typeParameters: readonly TypeParameterDeclaration[] | undefined = sortedTypeParametersAndDeclarations.length === 0 diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index 18f8e17750e2c..b9832c4dfd5f3 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -1,7 +1,6 @@ import { addToSeen, altDirectorySeparator, - arrayFrom, CallLikeExpression, CancellationToken, changeExtension, @@ -159,7 +158,7 @@ import { interface NameAndKindSet { add(value: NameAndKind): void; has(name: string): boolean; - values(): Iterator; + values(): IterableIterator; } const kindPrecedence = { [ScriptElementKind.directory]: 0, @@ -559,7 +558,7 @@ function getCompletionEntriesForRelativeModules(literalValue: string, scriptDire compilerOptions.rootDirs, literalValue, scriptDirectory, extensionOptions, compilerOptions, host, scriptPath); } else { - return arrayFrom(getCompletionEntriesForDirectoryFragment(literalValue, scriptDirectory, extensionOptions, host, /*moduleSpecifierIsRelative*/ false, scriptPath).values()); + return Array.from(getCompletionEntriesForDirectoryFragment(literalValue, scriptDirectory, extensionOptions, host, /*moduleSpecifierIsRelative*/ false, scriptPath).values()); } } @@ -594,7 +593,7 @@ function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs: string[] const basePath = compilerOptions.project || host.getCurrentDirectory(); const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); const baseDirectories = getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptDirectory, ignoreCase); - return flatMap(baseDirectories, baseDirectory => arrayFrom(getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensionOptions, host, /*moduleSpecifierIsRelative*/ true, exclude).values())); + return flatMap(baseDirectories, baseDirectory => Array.from(getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensionOptions, host, /*moduleSpecifierIsRelative*/ true, exclude).values())); } const enum ReferenceKind { @@ -892,7 +891,7 @@ function getCompletionEntriesForNonRelativeModules( } } - return arrayFrom(result.values()); + return Array.from(result.values()); } function getPatternFromFirstMatchingCondition(target: unknown, conditions: readonly string[]): string | undefined { @@ -1049,7 +1048,7 @@ function getTripleSlashReferenceCompletion(sourceFile: SourceFile, position: num const names = kind === "path" ? getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getExtensionOptions(compilerOptions, ReferenceKind.Filename, sourceFile), host, /*moduleSpecifierIsRelative*/ true, sourceFile.path) : kind === "types" ? getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, getFragmentDirectory(toComplete), getExtensionOptions(compilerOptions, ReferenceKind.ModuleSpecifier, sourceFile)) : Debug.fail(); - return addReplacementSpans(toComplete, range.pos + prefix.length, arrayFrom(names.values())); + return addReplacementSpans(toComplete, range.pos + prefix.length, Array.from(names.values())); } function getCompletionEntriesFromTypings(host: LanguageServiceHost, options: CompilerOptions, scriptPath: string, fragmentDirectory: string | undefined, extensionOptions: ExtensionOptions, result = createNameAndKindSet()): NameAndKindSet { diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index bda7ba595090c..a98e15b1d8360 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -1,6 +1,5 @@ import { addRange, - arrayFrom, BinaryExpression, CallExpression, CheckFlags, @@ -236,7 +235,7 @@ export function getSymbolModifiers(typeChecker: TypeChecker, symbol: Symbol): st if (symbol.flags & SymbolFlags.Optional) { modifiers.add(ScriptElementKindModifier.optionalModifier); } - return modifiers.size > 0 ? arrayFrom(modifiers.values()).join(",") : ScriptElementKindModifier.none; + return modifiers.size > 0 ? Array.from(modifiers.values()).join(",") : ScriptElementKindModifier.none; } /** @internal */ diff --git a/src/testRunner/unittests/compilerCore.ts b/src/testRunner/unittests/compilerCore.ts index 1b7f82118016f..45e839e1a5c6a 100644 --- a/src/testRunner/unittests/compilerCore.ts +++ b/src/testRunner/unittests/compilerCore.ts @@ -134,15 +134,15 @@ describe("unittests:: compilerCore", () => { const expected = [0, 1, 2, 3]; let actual: number[]; - actual = ts.arrayFrom(set.keys()); + actual = Array.from(set.keys()); actual.sort(); assert.deepEqual(actual, expected); - actual = ts.arrayFrom(set.values()); + actual = Array.from(set.values()); actual.sort(); assert.deepEqual(actual, expected); - const actualTuple = ts.arrayFrom(set.entries()); + const actualTuple = Array.from(set.entries()); assert.isFalse(actualTuple.some(([v, k]) => v !== k)); actual = actualTuple.map(([v, _]) => v); actual.sort(); diff --git a/src/testRunner/unittests/customTransforms.ts b/src/testRunner/unittests/customTransforms.ts index 28b1b61c88529..b20a7f7857aa9 100644 --- a/src/testRunner/unittests/customTransforms.ts +++ b/src/testRunner/unittests/customTransforms.ts @@ -20,10 +20,11 @@ describe("unittests:: customTransforms", () => { writeFile: (fileName, text) => outputs.set(fileName, text), }; - const program = ts.createProgram(ts.arrayFrom(fileMap.keys()), { newLine: ts.NewLineKind.LineFeed, ...options }, host); + const program = ts.createProgram(Array.from(fileMap.keys()), { newLine: ts.NewLineKind.LineFeed, ...options }, host); program.emit(/*targetSourceFile*/ undefined, host.writeFile, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ false, customTransformers); let content = ""; - for (const [file, text] of ts.arrayFrom(outputs.entries())) { + // TODO(jakebailey): redundant + for (const [file, text] of Array.from(outputs.entries())) { if (content) content += "\n\n"; content += `// [${file}]\n`; content += text; diff --git a/src/testRunner/unittests/programApi.ts b/src/testRunner/unittests/programApi.ts index 1ac47d50c2d19..a68b7419f4a76 100644 --- a/src/testRunner/unittests/programApi.ts +++ b/src/testRunner/unittests/programApi.ts @@ -12,7 +12,7 @@ function verifyMissingFilePaths(missingPaths: readonly ts.Path[], expected: read assert.isTrue(value, `${missing} to be ${value === undefined ? "not present" : "present only once"}, in actual: ${missingPaths} expected: ${expected}`); map.delete(missing); } - const notFound = ts.arrayFrom(ts.mapDefinedIterator(map.keys(), k => map.has(k) ? k : undefined)); + const notFound = Array.from(ts.mapDefinedIterator(map.keys(), k => map.has(k) ? k : undefined)); assert.equal(notFound.length, 0, `Not found ${notFound} in actual: ${missingPaths} expected: ${expected}`); } diff --git a/src/testRunner/unittests/tsc/helpers.ts b/src/testRunner/unittests/tsc/helpers.ts index cab632b7204dc..db7832b10b697 100644 --- a/src/testRunner/unittests/tsc/helpers.ts +++ b/src/testRunner/unittests/tsc/helpers.ts @@ -235,7 +235,7 @@ function storeDtsSignatures(sys: TscCompileSystem, programs: readonly CommandLin sys, (signature, sourceFiles) => { const exportedModules = ts.BuilderState.getExportedModules(state.exportedModulesMap && sourceFiles[0].exportedModulesFromDeclarationEmit); - dtsSignatureData.set(relativeToBuildInfo(resolvedPath), { signature, exportedModules: exportedModules && ts.arrayFrom(exportedModules.keys(), relativeToBuildInfo) }); + dtsSignatureData.set(relativeToBuildInfo(resolvedPath), { signature, exportedModules: exportedModules && Array.from(exportedModules.keys(), relativeToBuildInfo) }); }, ); }); @@ -707,7 +707,8 @@ function verifyTscEditDiscrepancies({ computeDtsSignatures: true, }); let headerAdded = false; - for (const outputFile of ts.arrayFrom(sys.writtenFiles.keys())) { + // TODO(jakebailey): redundant? + for (const outputFile of Array.from(sys.writtenFiles.keys())) { const cleanBuildText = sys.readFile(outputFile); const incrementalBuildText = newSys.readFile(outputFile); if (ts.isBuildInfoFile(outputFile)) { diff --git a/src/testRunner/unittests/tscWatch/incremental.ts b/src/testRunner/unittests/tscWatch/incremental.ts index 2773a739e6a80..bd38e5eea6c0d 100644 --- a/src/testRunner/unittests/tscWatch/incremental.ts +++ b/src/testRunner/unittests/tscWatch/incremental.ts @@ -202,8 +202,8 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => { configFilePath: config.path }); - assert.equal(ts.arrayFrom(state.referencedMap!.keys()).length, 0); - assert.equal(ts.arrayFrom(state.exportedModulesMap!.keys()).length, 0); + assert.equal(Array.from(state.referencedMap!.keys()).length, 0); + assert.equal(Array.from(state.exportedModulesMap!.keys()).length, 0); assert.equal(state.semanticDiagnosticsPerFile!.size, 3); assert.deepEqual(state.semanticDiagnosticsPerFile!.get(libFile.path as ts.Path), ts.emptyArray); diff --git a/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts b/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts index cf3ca9ac028d6..ba1451d3edfb5 100644 --- a/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts +++ b/src/testRunner/unittests/tsserver/cachingFileSystemInformation.ts @@ -62,7 +62,7 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS } function logCacheEntry(logger: Logger, callback: CalledMaps) { - const result = ts.arrayFrom<[string, (true | CalledWithFiveArgs)[]], { key: string, count: number }>(calledMaps[callback].entries(), ([key, arr]) => ({ key, count: arr.length })); + const result = Array.from<[string, (true | CalledWithFiveArgs)[]], { key: string, count: number }>(calledMaps[callback].entries(), ([key, arr]) => ({ key, count: arr.length })); logger.info(`${callback}:: ${JSON.stringify(result)}`); calledMaps[callback].clear(); } diff --git a/src/testRunner/unittests/tsserver/helpers.ts b/src/testRunner/unittests/tsserver/helpers.ts index 62ae117c734bd..2804a216b0b90 100644 --- a/src/testRunner/unittests/tsserver/helpers.ts +++ b/src/testRunner/unittests/tsserver/helpers.ts @@ -881,7 +881,7 @@ export function verifyGetErrScenario(scenario: VerifyGetErrScenario) { } export function verifyDynamic(service: ts.server.ProjectService, path: string) { - const info = ts.Debug.checkDefined(service.filenameToScriptInfo.get(path), `Expected ${path} in :: ${JSON.stringify(ts.arrayFrom(service.filenameToScriptInfo.entries(), ([key, f]) => ({ key, fileName: f.fileName, path: f.path })))}`); + const info = ts.Debug.checkDefined(service.filenameToScriptInfo.get(path), `Expected ${path} in :: ${JSON.stringify(Array.from(service.filenameToScriptInfo.entries(), ([key, f]) => ({ key, fileName: f.fileName, path: f.path })))}`); assert.isTrue(info.isDynamic); } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 6f6e0a8fb4b32..9f57b4b2cfbf5 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3970,7 +3970,7 @@ declare namespace ts { interface ReadonlyCollection { readonly size: number; has(key: K): boolean; - keys(): Iterator; + keys(): IterableIterator; } /** Common write methods for ES6 Map/Set. */ interface Collection extends ReadonlyCollection { diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 7c3088b485c5d..2aeded2834a78 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -35,7 +35,7 @@ declare namespace ts { interface ReadonlyCollection { readonly size: number; has(key: K): boolean; - keys(): Iterator; + keys(): IterableIterator; } /** Common write methods for ES6 Map/Set. */ interface Collection extends ReadonlyCollection { From 308e0eb407eac00326166643ca752efb79dd5e72 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 15 Dec 2022 20:10:28 -0800 Subject: [PATCH 05/22] Fix jsTyping --- src/jsTyping/jsTyping.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jsTyping/jsTyping.ts b/src/jsTyping/jsTyping.ts index c927d99e0b771..1278b8bff5b36 100644 --- a/src/jsTyping/jsTyping.ts +++ b/src/jsTyping/jsTyping.ts @@ -141,7 +141,7 @@ export function loadSafeList(host: TypingResolutionHost, safeListPath: Path): Sa /** @internal */ export function loadTypesMap(host: TypingResolutionHost, typesMapPath: Path): SafeList | undefined { const result = readConfigFile(typesMapPath, path => host.readFile(path)); - if (result.config) { + if (result.config?.simpleMap) { return new Map(Object.entries(result.config.simpleMap)); } return undefined; From fb15fc06cd2196b109126a2369672ca4642f4298 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 15 Dec 2022 20:13:04 -0800 Subject: [PATCH 06/22] Remove Collection --- src/compiler/builder.ts | 3 +-- src/compiler/corePublic.ts | 12 ------------ src/compiler/utilities.ts | 10 ++++------ src/server/editorServices.ts | 5 ++--- src/services/codefixes/convertToEsModule.ts | 3 +-- src/testRunner/unittests/tsc/helpers.ts | 7 ++----- tests/baselines/reference/api/tsserverlibrary.d.ts | 11 ----------- tests/baselines/reference/api/typescript.d.ts | 11 ----------- 8 files changed, 10 insertions(+), 52 deletions(-) diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 1893cbcaeb1df..4b7274bffac8c 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -65,7 +65,6 @@ import { Program, ProjectReference, ReadBuildProgramHost, - ReadonlyCollection, returnFalse, returnUndefined, SemanticDiagnosticsBuilderProgram, @@ -276,7 +275,7 @@ export function getPendingEmitKind(optionsOrEmitKind: CompilerOptions | BuilderF return result; } -function hasSameKeys(map1: ReadonlyCollection | undefined, map2: ReadonlyCollection | undefined): boolean { +function hasSameKeys(map1: ReadonlyMap | ReadonlySet | undefined, map2: ReadonlyMap | ReadonlySet | undefined): boolean { // Has same size and every key is present in both maps return map1 === map2 || map1 !== undefined && map2 !== undefined && map1.size === map2.size && !forEachKey(map1, key => !map2.has(key)); } diff --git a/src/compiler/corePublic.ts b/src/compiler/corePublic.ts index de173a1fc04b8..d4485e6b0302d 100644 --- a/src/compiler/corePublic.ts +++ b/src/compiler/corePublic.ts @@ -23,18 +23,6 @@ export interface SortedArray extends Array { " __sortedArrayBrand": any; } -/** Common read methods for ES6 Map/Set. */ -export interface ReadonlyCollection { - readonly size: number; - has(key: K): boolean; - keys(): IterableIterator; -} - -/** Common write methods for ES6 Map/Set. */ -export interface Collection extends ReadonlyCollection { - delete(key: K): boolean; - clear(): void; -} /** Array that is only intended to be pushed to, never read. */ export interface Push { push(...values: T[]): void; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 94ef86cc58fe2..90f71e2d20df2 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -423,7 +423,6 @@ import { PropertySignature, PseudoBigInt, QualifiedName, - ReadonlyCollection, ReadonlyTextRange, removeTrailingDirectorySeparator, RequireOrImportCall, @@ -653,8 +652,7 @@ export function forEachAncestor(node: Node, callback: (n: Node) => T | undefi */ export function forEachEntry(map: ReadonlyMap, callback: (value: V, key: K) => U | undefined): U | undefined { const iterator = map.entries(); - for (let iterResult = iterator.next(); !iterResult.done; iterResult = iterator.next()) { - const [key, value] = iterResult.value; + for (const [key, value] of iterator) { const result = callback(value, key); if (result) { return result; @@ -668,10 +666,10 @@ export function forEachEntry(map: ReadonlyMap, callback: (value: * * @internal */ -export function forEachKey(map: ReadonlyCollection, callback: (key: K) => T | undefined): T | undefined { +export function forEachKey(map: ReadonlyMap | ReadonlySet, callback: (key: K) => T | undefined): T | undefined { const iterator = map.keys(); - for (let iterResult = iterator.next(); !iterResult.done; iterResult = iterator.next()) { - const result = callback(iterResult.value); + for (const key of iterator) { + const result = callback(key); if (result) { return result; } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index f983a660203c6..d4126d121ab0d 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -143,7 +143,6 @@ import { ProjectPackageJsonInfo, ProjectReference, ReadMapFile, - ReadonlyCollection, removeFileExtension, removeIgnoredPath, removeMinAndVersionNumbers, @@ -3667,7 +3666,7 @@ export class ProjectService { } /** @internal */ - loadAncestorProjectTree(forProjects?: ReadonlyCollection) { + loadAncestorProjectTree(forProjects?: ReadonlyMap | ReadonlySet) { forProjects = forProjects || mapDefinedEntries( this.configuredProjects, (key, project) => !project.isInitialLoadPending() ? [key, true] : undefined @@ -3685,7 +3684,7 @@ export class ProjectService { } } - private ensureProjectChildren(project: ConfiguredProject, forProjects: ReadonlyCollection, seenProjects: Set) { + private ensureProjectChildren(project: ConfiguredProject, forProjects: ReadonlyMap | ReadonlySet, seenProjects: Set) { if (!tryAddToSet(seenProjects, project.canonicalConfigFilePath)) return; // If this project disables child load ignore it diff --git a/src/services/codefixes/convertToEsModule.ts b/src/services/codefixes/convertToEsModule.ts index ed38f5f58c4c5..447533c987323 100644 --- a/src/services/codefixes/convertToEsModule.ts +++ b/src/services/codefixes/convertToEsModule.ts @@ -68,7 +68,6 @@ import { PropertyAccessExpression, QuotePreference, rangeContainsRange, - ReadonlyCollection, ScriptTarget, some, SourceFile, @@ -388,7 +387,7 @@ function convertReExportAll(reExported: StringLiteralLike, checker: TypeChecker) // `module.exports = require("x");` ==> `export * from "x"; export { default } from "x";` const moduleSpecifier = reExported.text; const moduleSymbol = checker.getSymbolAtLocation(reExported); - const exports = moduleSymbol ? moduleSymbol.exports! : emptyMap as ReadonlyCollection<__String>; + const exports = moduleSymbol ? moduleSymbol.exports! : emptyMap as ReadonlyMap<__String, never>; return exports.has(InternalSymbolName.ExportEquals) ? [[reExportDefault(moduleSpecifier)], true] : !exports.has(InternalSymbolName.Default) ? [[reExportStar(moduleSpecifier)], false] : // If there's some non-default export, must include both `export *` and `export default`. diff --git a/src/testRunner/unittests/tsc/helpers.ts b/src/testRunner/unittests/tsc/helpers.ts index db7832b10b697..eeeb9ee721a2f 100644 --- a/src/testRunner/unittests/tsc/helpers.ts +++ b/src/testRunner/unittests/tsc/helpers.ts @@ -438,12 +438,9 @@ function addLibAndMakeReadonly(fs: vfs.FileSystem, libContentToAppend?: string) fs.makeReadonly(); } -export function generateSourceMapBaselineFiles(sys: ts.System & { writtenFiles: ts.ReadonlyCollection; }) { +export function generateSourceMapBaselineFiles(sys: ts.System & { writtenFiles: Map | Set; }) { const mapFileNames = ts.mapDefinedIterator(sys.writtenFiles.keys(), f => f.endsWith(".map") ? f : undefined); - while (true) { - const result = mapFileNames.next(); - if (result.done) break; - const mapFile = result.value; + for (const mapFile of mapFileNames) { const text = Harness.SourceMapRecorder.getSourceMapRecordWithSystem(sys, mapFile); sys.writeFile(`${mapFile}.baseline.txt`, text); } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 9f57b4b2cfbf5..9a9d1f7bebd7e 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3966,17 +3966,6 @@ declare namespace ts { interface SortedArray extends Array { " __sortedArrayBrand": any; } - /** Common read methods for ES6 Map/Set. */ - interface ReadonlyCollection { - readonly size: number; - has(key: K): boolean; - keys(): IterableIterator; - } - /** Common write methods for ES6 Map/Set. */ - interface Collection extends ReadonlyCollection { - delete(key: K): boolean; - clear(): void; - } /** Array that is only intended to be pushed to, never read. */ interface Push { push(...values: T[]): void; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 2aeded2834a78..611633da9f02b 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -31,17 +31,6 @@ declare namespace ts { interface SortedArray extends Array { " __sortedArrayBrand": any; } - /** Common read methods for ES6 Map/Set. */ - interface ReadonlyCollection { - readonly size: number; - has(key: K): boolean; - keys(): IterableIterator; - } - /** Common write methods for ES6 Map/Set. */ - interface Collection extends ReadonlyCollection { - delete(key: K): boolean; - clear(): void; - } /** Array that is only intended to be pushed to, never read. */ interface Push { push(...values: T[]): void; From 3da3aeedd5bc4c7f0a7d8b1067906a4674b7df88 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 15 Dec 2022 20:53:06 -0800 Subject: [PATCH 07/22] Eliminate most manual iteration --- src/compiler/builderState.ts | 5 +- src/compiler/checker.ts | 8 +- src/compiler/commandLineParser.ts | 5 +- src/compiler/core.ts | 92 +++++++++---------- src/compiler/sourcemap.ts | 4 +- src/harness/collectionsImpl.ts | 27 +----- src/harness/harnessIO.ts | 10 +- src/harness/typeWriter.ts | 14 +-- src/harness/vfsUtil.ts | 59 ++++-------- src/server/editorServices.ts | 9 +- src/server/session.ts | 5 +- src/testRunner/unittests/config/showConfig.ts | 5 +- 12 files changed, 89 insertions(+), 154 deletions(-) diff --git a/src/compiler/builderState.ts b/src/compiler/builderState.ts index 014d14725bd93..638a78f320cce 100644 --- a/src/compiler/builderState.ts +++ b/src/compiler/builderState.ts @@ -520,10 +520,7 @@ export namespace BuilderState { seenMap.add(path); const references = state.referencedMap.getValues(path); if (references) { - const iterator = references.keys(); - for (let iterResult = iterator.next(); !iterResult.done; iterResult = iterator.next()) { - queue.push(iterResult.value); - } + queue.push(...references.keys()); } } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 93a70c76de069..a05fe3062fac0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -180,6 +180,7 @@ import { first, firstDefined, firstOrUndefined, + firstOrUndefinedIterator, flatMap, flatten, FlowArrayMutation, @@ -19014,8 +19015,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ) { // Assignability failure - check each prop individually, and if that fails, fall back on the bad error span let reportedError = false; - for (let status = iterator.next(); !status.done; status = iterator.next()) { - const { errorNode: prop, innerExpression: next, nameType, errorMessage } = status.value; + for (const value of iterator) { + const { errorNode: prop, innerExpression: next, nameType, errorMessage } = value; let targetPropType = getBestMatchIndexedAccessTypeOrUndefined(source, target, nameType); if (!targetPropType || targetPropType.flags & TypeFlags.IndexedAccess) continue; // Don't elaborate on indexes on generic variables let sourcePropType = getIndexedAccessTypeOrUndefined(source, nameType); @@ -23501,8 +23502,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getUnmatchedProperty(source: Type, target: Type, requireOptionalProperties: boolean, matchDiscriminantProperties: boolean): Symbol | undefined { - const result = getUnmatchedProperties(source, target, requireOptionalProperties, matchDiscriminantProperties).next(); - if (!result.done) return result.value; + return firstOrUndefinedIterator(getUnmatchedProperties(source, target, requireOptionalProperties, matchDiscriminantProperties)); } function tupleTypesDefinitelyUnrelated(source: TupleTypeReference, target: TupleTypeReference) { diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index fba058e04aa07..f55824081fba4 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -40,6 +40,7 @@ import { find, findIndex, firstDefined, + firstOrUndefinedIterator, flatten, forEach, forEachEntry, @@ -4030,8 +4031,8 @@ function getDefaultValueForOption(option: CommandLineOption): {} { case "object": return {}; default: - const iterResult = option.type.keys().next(); - if (!iterResult.done) return iterResult.value; + const value = firstOrUndefinedIterator(option.type.keys()); + if (value !== undefined) return value; return Debug.fail("Expected 'option.type' to have entries."); } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 7aabbc3a170fe..8047b3ed8a99f 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -84,25 +84,24 @@ export function firstDefined(array: readonly T[] | undefined, callback: (e } /** @internal */ -export function firstDefinedIterator(iter: Iterator, callback: (element: T) => U | undefined): U | undefined { - while (true) { - const iterResult = iter.next(); - if (iterResult.done) { - return undefined; - } - const result = callback(iterResult.value); +export function firstDefinedIterator(iter: Iterable, callback: (element: T) => U | undefined): U | undefined { + for (const value of iter) { + const result = callback(value); if (result !== undefined) { return result; } } + return undefined; } /** @internal */ -export function reduceLeftIterator(iterator: Iterator | undefined, f: (memo: U, value: T, i: number) => U, initial: U): U { +export function reduceLeftIterator(iterator: Iterable | undefined, f: (memo: U, value: T, i: number) => U, initial: U): U { let result = initial; if (iterator) { - for (let step = iterator.next(), pos = 0; !step.done; step = iterator.next(), pos++) { - result = f(result, step.value, pos); + let pos = 0; + for (const value of iterator) { + result = f(result, value, pos); + pos++; } } return result; @@ -110,10 +109,10 @@ export function reduceLeftIterator(iterator: Iterator | undefined, f: ( /** @internal */ export function zipWith(arrayA: readonly T[], arrayB: readonly U[], callback: (a: T, b: U, index: number) => V): V[] { - const result: V[] = []; Debug.assertEqual(arrayA.length, arrayB.length); + const result: V[] = new Array(arrayA.length); for (let i = 0; i < arrayA.length; i++) { - result.push(callback(arrayA[i], arrayB[i], i)); + result[i] = callback(arrayA[i], arrayB[i], i); } return result; } @@ -1185,12 +1184,30 @@ export function firstOrUndefined(array: readonly T[] | undefined): T | undefi return array === undefined || array.length === 0 ? undefined : array[0]; } +/** @internal */ +export function firstOrUndefinedIterator(iter: Iterable | undefined): T | undefined { + if (iter) { + for (const value of iter) { + return value; + } + } + return undefined; +} + /** @internal */ export function first(array: readonly T[]): T { Debug.assert(array.length !== 0); return array[0]; } +/** @internal */ +export function firstIterator(iter: Iterable): T { + for (const value of iter) { + return value; + } + Debug.fail("iterator is empty"); +} + /** * Returns the last element of an array if non-empty, `undefined` otherwise. * @@ -1692,36 +1709,15 @@ export function createSet(getHashCode: (element: TElem const multiMap = new Map(); let size = 0; - function getElementIterator(): IterableIterator { - const valueIt = multiMap.values(); - let arrayIt: Iterator | undefined; - const it: IterableIterator = { - next: () => { - while (true) { - if (arrayIt) { - const n = arrayIt.next(); - if (!n.done) { - return { value: n.value }; - } - arrayIt = undefined; - } - else { - const n = valueIt.next(); - if (n.done) { - return { value: undefined, done: true }; - } - if (!isArray(n.value)) { - return { value: n.value }; - } - arrayIt = arrayIterator(n.value); - } - } - }, - [Symbol.iterator]: () => { - return it; + function *getElementIterator(): IterableIterator { + for (const value of multiMap.values()) { + if (isArray(value)) { + yield* value; + } + else { + yield value; } - }; - return it; + } } const set: Set = { @@ -1821,16 +1817,10 @@ export function createSet(getHashCode: (element: TElem values(): IterableIterator { return getElementIterator(); }, - entries(): IterableIterator<[TElement, TElement]> { - const it = getElementIterator(); - const it2: IterableIterator<[TElement, TElement]> = { - next: () => { - const n = it.next(); - return n.done ? n : { value: [ n.value, n.value ] }; - }, - [Symbol.iterator]: () => it2, - }; - return it2; + *entries(): IterableIterator<[TElement, TElement]> { + for (const value of getElementIterator()) { + yield [value, value]; + } }, [Symbol.iterator]: () => { return getElementIterator(); diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index 0a5e707992fed..fa8ffc896fadb 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -179,8 +179,7 @@ export function createSourceMapGenerator(host: EmitHost, file: string, sourceRoo const sourceIndexToNewSourceIndexMap: number[] = []; let nameIndexToNewNameIndexMap: number[] | undefined; const mappingIterator = decodeMappings(map.mappings); - for (let iterResult = mappingIterator.next(); !iterResult.done; iterResult = mappingIterator.next()) { - const raw = iterResult.value; + for (const raw of mappingIterator) { if (end && ( raw.generatedLine > end.line || (raw.generatedLine === end.line && raw.generatedCharacter > end.character))) { @@ -462,6 +461,7 @@ export function decodeMappings(mappings: string): MappingsDecoder { let nameIndex = 0; let error: string | undefined; + // TODO(jakebailey): can we implement this without writing next ourselves? return { get pos() { return pos; }, get error() { return error; }, diff --git a/src/harness/collectionsImpl.ts b/src/harness/collectionsImpl.ts index 541358ac95862..cc43361489205 100644 --- a/src/harness/collectionsImpl.ts +++ b/src/harness/collectionsImpl.ts @@ -17,15 +17,8 @@ export class SortedMap { this._comparer = typeof comparer === "object" ? comparer.comparer : comparer; this._order = typeof comparer === "object" && comparer.sort === "insertion" ? [] : undefined; if (iterable) { - const iterator = getIterator(iterable); - try { - for (let i = nextResult(iterator); i; i = nextResult(iterator)) { - const [key, value] = i.value; - this.set(key, value); - } - } - finally { - closeIterator(iterator); + for (const [key, value] of iterable) { + this.set(key, value); } } } @@ -216,7 +209,7 @@ export class SortedMap { } } -export function insertAt(array: T[], index: number, value: T): void { +function insertAt(array: T[], index: number, value: T): void { if (index === 0) { array.unshift(value); } @@ -231,20 +224,6 @@ export function insertAt(array: T[], index: number, value: T): void { } } -export function getIterator(iterable: Iterable): Iterator { - return iterable[Symbol.iterator](); -} - -export function nextResult(iterator: Iterator): IteratorResult | undefined { - const result = iterator.next(); - return result.done ? undefined : result; -} - -export function closeIterator(iterator: Iterator) { - const fn = iterator.return; - if (typeof fn === "function") fn.call(iterator); -} - /** * A collection of metadata that supports inheritance. */ diff --git a/src/harness/harnessIO.ts b/src/harness/harnessIO.ts index 89909e80693ba..9add3b76f7517 100644 --- a/src/harness/harnessIO.ts +++ b/src/harness/harnessIO.ts @@ -551,7 +551,7 @@ export namespace Compiler { export function getErrorBaseline(inputFiles: readonly TestFile[], diagnostics: readonly ts.Diagnostic[], pretty?: boolean) { let outputLines = ""; const gen = iterateErrorBaseline(inputFiles, diagnostics, { pretty }); - for (let {done, value} = gen.next(); !done; { done, value } = gen.next()) { + for (const value of gen) { const [, content] = value; outputLines += content; } @@ -791,7 +791,7 @@ export namespace Compiler { function generateBaseLine(isSymbolBaseline: boolean, skipBaseline?: boolean): string | null { let result = ""; const gen = iterateBaseLine(isSymbolBaseline, skipBaseline); - for (let {done, value} = gen.next(); !done; { done, value } = gen.next()) { + for (const value of gen) { const [, content] = value; result += content; } @@ -810,7 +810,7 @@ export namespace Compiler { const codeLines = ts.flatMap(file.content.split(/\r?\n/g), e => e.split(/[\r\u2028\u2029]/g)); const gen: IterableIterator = isSymbolBaseline ? fullWalker.getSymbols(unitName) : fullWalker.getTypes(unitName); let lastIndexWritten: number | undefined; - for (let {done, value: result} = gen.next(); !done; { done, value: result } = gen.next()) { + for (const result of gen) { if (isSymbolBaseline && !result.symbol) { return; } @@ -950,7 +950,7 @@ export namespace Compiler { const gen = iterateOutputs(outputFiles); // Emit them let result = ""; - for (let {done, value} = gen.next(); !done; { done, value } = gen.next()) { + for (const value of gen) { // Some extra spacing if this isn't the first file if (result.length) { result += "\r\n\r\n"; @@ -1438,7 +1438,7 @@ export namespace Baseline { // eslint-disable-next-line no-null/no-null if (gen !== null) { - for (let {done, value} = gen.next(); !done; { done, value } = gen.next()) { + for (const value of gen) { const [name, content, count] = value as [string, string, number | undefined]; if (count === 0) continue; // Allow error reporter to skip writing files without errors const relativeFileName = relativeFileBase + "/" + name + extension; diff --git a/src/harness/typeWriter.ts b/src/harness/typeWriter.ts index 6593623c4d71f..3d3602b32decd 100644 --- a/src/harness/typeWriter.ts +++ b/src/harness/typeWriter.ts @@ -52,25 +52,19 @@ export class TypeWriterWalker { const sourceFile = this.program.getSourceFile(fileName)!; this.currentSourceFile = sourceFile; const gen = this.visitNode(sourceFile, /*isSymbolWalk*/ true); - for (let {done, value} = gen.next(); !done; { done, value } = gen.next()) { - yield value as TypeWriterSymbolResult; - } + yield* gen as IterableIterator; } public *getTypes(fileName: string): IterableIterator { const sourceFile = this.program.getSourceFile(fileName)!; this.currentSourceFile = sourceFile; const gen = this.visitNode(sourceFile, /*isSymbolWalk*/ false); - for (let {done, value} = gen.next(); !done; { done, value } = gen.next()) { - yield value as TypeWriterTypeResult; - } + yield* gen as IterableIterator; } private *visitNode(node: ts.Node, isSymbolWalk: boolean): IterableIterator { const gen = forEachASTNode(node); - let res = gen.next(); - for (; !res.done; res = gen.next()) { - const {value: node} = res; + for (const node of gen) { if (ts.isExpressionNode(node) || node.kind === ts.SyntaxKind.Identifier || ts.isDeclarationName(node)) { const result = this.writeTypeOrSymbol(node, isSymbolWalk); if (result) { @@ -191,4 +185,4 @@ export class TypeWriterWalker { symbol: symbolString }; } -} \ No newline at end of file +} diff --git a/src/harness/vfsUtil.ts b/src/harness/vfsUtil.ts index 35adcfb354b2c..5b8d61e0445f6 100644 --- a/src/harness/vfsUtil.ts +++ b/src/harness/vfsUtil.ts @@ -84,16 +84,9 @@ export class FileSystem { let cwd = options.cwd; if ((!cwd || !vpath.isRoot(cwd)) && this._lazy.links) { - const iterator = collections.getIterator(this._lazy.links.keys()); - try { - for (let i = collections.nextResult(iterator); i; i = collections.nextResult(iterator)) { - const name = i.value; - cwd = cwd ? vpath.resolve(name, cwd) : name; - break; - } - } - finally { - collections.closeIterator(iterator); + for (const name of this._lazy.links.keys()) { + cwd = cwd ? vpath.resolve(name, cwd) : name; + break; } } @@ -384,28 +377,21 @@ export class FileSystem { public getFileListing(): string { let result = ""; const printLinks = (dirname: string | undefined, links: collections.SortedMap) => { - const iterator = collections.getIterator(links); - try { - for (let i = collections.nextResult(iterator); i; i = collections.nextResult(iterator)) { - const [name, node] = i.value; - const path = dirname ? vpath.combine(dirname, name) : name; - const marker = vpath.compare(this._cwd, path, this.ignoreCase) === 0 ? "*" : " "; - if (result) result += "\n"; - result += marker; - if (isDirectory(node)) { - result += vpath.addTrailingSeparator(path); - printLinks(path, this._getLinks(node)); - } - else if (isFile(node)) { - result += path; - } - else if (isSymlink(node)) { - result += path + " -> " + node.symlink; - } + for (const [name, node] of links) { + const path = dirname ? vpath.combine(dirname, name) : name; + const marker = vpath.compare(this._cwd, path, this.ignoreCase) === 0 ? "*" : " "; + if (result) result += "\n"; + result += marker; + if (isDirectory(node)) { + result += vpath.addTrailingSeparator(path); + printLinks(path, this._getLinks(node)); + } + else if (isFile(node)) { + result += path; + } + else if (isSymlink(node)) { + result += path + " -> " + node.symlink; } - } - finally { - collections.closeIterator(iterator); } }; printLinks(/*dirname*/ undefined, this._getRootLinks()); @@ -989,15 +975,8 @@ export class FileSystem { } private _copyShadowLinks(source: ReadonlyMap, target: collections.SortedMap) { - const iterator = collections.getIterator(source); - try { - for (let i = collections.nextResult(iterator); i; i = collections.nextResult(iterator)) { - const [name, root] = i.value; - target.set(name, this._getShadow(root)); - } - } - finally { - collections.closeIterator(iterator); + for (const [name, root] of source) { + target.set(name, this._getShadow(root)); } } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index d4126d121ab0d..f639d67592970 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -821,7 +821,7 @@ export interface OpenFileArguments { /** @internal */ export interface ChangeFileArguments { fileName: string; - changes: Iterator; + changes: Iterable; } export interface WatchOptionsAndErrors { @@ -3954,11 +3954,8 @@ export class ProjectService { } /** @internal */ - applyChangesToFile(scriptInfo: ScriptInfo, changes: Iterator) { - while (true) { - const iterResult = changes.next(); - if (iterResult.done) break; - const change = iterResult.value; + applyChangesToFile(scriptInfo: ScriptInfo, changes: Iterable) { + for (const change of changes) { scriptInfo.editContent(change.span.start, change.span.start + change.span.length, change.newText); } } diff --git a/src/server/session.ts b/src/server/session.ts index 0104c304d3db6..69f6a41f865c6 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -42,6 +42,7 @@ import { find, FindAllReferences, first, + firstIterator, firstOrUndefined, flatMap, flatMapToMutable, @@ -752,9 +753,7 @@ function getPerProjectReferences( // In the common case where there's only one project, return a simpler result to make // it easier for the caller to skip post-processing. if (resultsMap.size === 1) { - const it = resultsMap.values().next(); - Debug.assert(!it.done); - return it.value; + return firstIterator(resultsMap.values()); } return resultsMap; diff --git a/src/testRunner/unittests/config/showConfig.ts b/src/testRunner/unittests/config/showConfig.ts index a815ec7d7750c..f2a6f95e99f53 100644 --- a/src/testRunner/unittests/config/showConfig.ts +++ b/src/testRunner/unittests/config/showConfig.ts @@ -177,9 +177,8 @@ describe("unittests:: config:: showConfig", () => { break; } default: { - const iterResult = option.type.keys().next(); - if (iterResult.done) return ts.Debug.fail("Expected 'option.type' to have entries"); - const val = iterResult.value; + const val = ts.firstOrUndefinedIterator(option.type.keys()); + if (val === undefined) return ts.Debug.fail("Expected 'option.type' to have entries"); if (option.isTSConfigOnly) { args = ["-p", "tsconfig.json"]; optionValue = { [option.name]: val }; From 7c6e9a09eb04e1d6059f1c1dae5f0abeff1bebd7 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 15 Dec 2022 20:59:28 -0800 Subject: [PATCH 08/22] Eliminate arrayIterator --- src/compiler/core.ts | 6 ----- src/compiler/transformers/declarations.ts | 2 +- src/server/session.ts | 3 +-- .../unittests/tsserver/externalProjects.ts | 2 +- .../unittests/tsserver/typingsInstaller.ts | 24 +++++++++---------- 5 files changed, 15 insertions(+), 22 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 8047b3ed8a99f..28e1c71d8c6bc 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1124,12 +1124,6 @@ export function sort(array: readonly T[], comparer?: Comparer): SortedRead return (array.length === 0 ? array : array.slice().sort(comparer)) as SortedReadonlyArray; } -/** @internal */ -export function *arrayIterator(array: readonly T[]) { - // TODO(jakebailey): remove? - yield* array; -} - /** @internal */ export function *arrayReverseIterator(array: readonly T[]) { for (let i = array.length - 1; i >= 0; i--) { diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 1266d0d2d39f7..a01077f85ccee 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -572,7 +572,7 @@ export function transformDeclarations(context: TransformationContext) { return updated; function getLibReferences() { - return map(Array.from(libs.keys()), lib => ({ fileName: lib, pos: -1, end: -1 })); + return Array.from(libs.keys(), lib => ({ fileName: lib, pos: -1, end: -1 })); } function getFileReferencesForUsedTypeReferences() { diff --git a/src/server/session.ts b/src/server/session.ts index 69f6a41f865c6..0fbf3030b06dd 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1,5 +1,4 @@ import { - arrayIterator, arrayReverseIterator, CallHierarchyIncomingCall, CallHierarchyItem, @@ -3163,7 +3162,7 @@ export class Session implements EventSender { this.changeSeq++; this.projectService.applyChangesInOpenFiles( request.arguments.openFiles, - request.arguments.changedFiles && mapIterator(arrayIterator(request.arguments.changedFiles), file => ({ + request.arguments.changedFiles && mapIterator(request.arguments.changedFiles, file => ({ fileName: file.fileName, // apply changes in reverse order changes: arrayReverseIterator(file.changes) diff --git a/src/testRunner/unittests/tsserver/externalProjects.ts b/src/testRunner/unittests/tsserver/externalProjects.ts index dfa9ec8b3264b..e52ef0af13766 100644 --- a/src/testRunner/unittests/tsserver/externalProjects.ts +++ b/src/testRunner/unittests/tsserver/externalProjects.ts @@ -244,7 +244,7 @@ describe("unittests:: tsserver:: ExternalProjects", () => { verifyDynamic(projectService, "/^scriptdocument1 file1.ts"); externalFiles[0].content = "let x =1;"; - projectService.applyChangesInOpenFiles(ts.arrayIterator(externalFiles)); + projectService.applyChangesInOpenFiles(externalFiles); }); it("when file name starts with ^", () => { diff --git a/src/testRunner/unittests/tsserver/typingsInstaller.ts b/src/testRunner/unittests/tsserver/typingsInstaller.ts index 2baee5315ddd4..aaa1780dd22d7 100644 --- a/src/testRunner/unittests/tsserver/typingsInstaller.ts +++ b/src/testRunner/unittests/tsserver/typingsInstaller.ts @@ -2001,13 +2001,13 @@ describe("unittests:: tsserver:: typingsInstaller:: recomputing resolutions of u checkProjectActualFiles(proj, typingFiles.map(f => f.path).concat(app.path, fooo.path)); const foooResolution2 = verifyResolvedModuleOfFooo(proj); assert.strictEqual(foooResolution1, foooResolution2); - projectService.applyChangesInOpenFiles(/*openFiles*/ undefined, ts.arrayIterator([{ + projectService.applyChangesInOpenFiles(/*openFiles*/ undefined, [{ fileName: app.path, - changes: ts.arrayIterator([{ + changes: [{ span: { start: 0, length: 0 }, newText: `import * as bar from "bar";` - }]) - }])); + }] + }]); host.runQueuedTimeoutCallbacks(); // Update the graph // Update the typing host.checkTimeoutQueueLength(0); @@ -2084,16 +2084,16 @@ declare module "stream" { checkProjectActualFiles(proj, [file.path, libFile.path, nodeTyping.path]); projectService.applyChangesInOpenFiles( /*openFiles*/ undefined, - ts.arrayIterator([{ + [{ fileName: file.path, - changes: ts.arrayIterator([{ + changes: [{ span: { start: file.content.indexOf(`"stream"`) + 2, length: 0 }, newText: " " - }]) - }]), + }] + }], /*closedFiles*/ undefined ); // Below timeout Updates the typings to empty array because of "s tream" as unsresolved import @@ -2104,13 +2104,13 @@ declare module "stream" { // Here, since typings dont change, there is no timeout scheduled host.checkTimeoutQueueLength(0); checkProjectActualFiles(proj, [file.path, libFile.path, nodeTyping.path]); - projectService.applyChangesInOpenFiles(/*openFiles*/ undefined, ts.arrayIterator([{ + projectService.applyChangesInOpenFiles(/*openFiles*/ undefined, [{ fileName: file.path, - changes: ts.arrayIterator([{ + changes: [{ span: { start: file.content.indexOf("const"), length: 0 }, newText: `const bar = require("bar");` - }]) - }])); + }] + }]); proj.updateGraph(); // Update the graph checkProjectActualFiles(proj, [file.path, libFile.path, nodeTyping.path]); // Update the typing From 15d7bf92cc19e0cb2705301f859301545a101cba Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 15 Dec 2022 21:05:49 -0800 Subject: [PATCH 09/22] Skip an array.from --- src/services/codefixes/fixAddMissingMember.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index 3b7a05a742787..e344dab4479e0 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -23,6 +23,7 @@ import { findIndex, firstDefined, firstOrUndefined, + firstOrUndefinedIterator, FunctionExpression, getCheckFlags, getClassLikeDeclarationOfSymbol, @@ -664,7 +665,7 @@ function tryGetValueFromType(context: CodeFixContextBase, checker: TypeChecker, return factory.createFalse(); } if (type.flags & TypeFlags.EnumLike) { - const enumMember = type.symbol.exports ? firstOrUndefined(Array.from(type.symbol.exports.values())) : type.symbol; + const enumMember = type.symbol.exports ? firstOrUndefinedIterator(type.symbol.exports.values()) : type.symbol; const name = checker.symbolToExpression(type.symbol.parent ? type.symbol.parent : type.symbol, SymbolFlags.Value, /*enclosingDeclaration*/ undefined, /*flags*/ undefined); return enumMember === undefined || name === undefined ? factory.createNumericLiteral(0) : factory.createPropertyAccessExpression(name, checker.symbolToString(enumMember)); } From 67025d715165c68c0e83a1be4a030b2a45b71c97 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 15 Dec 2022 21:11:29 -0800 Subject: [PATCH 10/22] Remove sum function --- src/compiler/checker.ts | 7 +++---- src/compiler/core.ts | 9 --------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a05fe3062fac0..c5ac7949c8ee2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -925,7 +925,6 @@ import { stripQuotes, StructuredType, SubstitutionType, - sum, SuperCall, SwitchStatement, Symbol, @@ -1435,9 +1434,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // extra cost of calling `getParseTreeNode` when calling these functions from inside the // checker. const checker: TypeChecker = { - getNodeCount: () => sum(host.getSourceFiles(), "nodeCount"), - getIdentifierCount: () => sum(host.getSourceFiles(), "identifierCount"), - getSymbolCount: () => sum(host.getSourceFiles(), "symbolCount") + symbolCount, + getNodeCount: () => reduceLeft(host.getSourceFiles(), (n, s) => n + s.nodeCount, 0), + getIdentifierCount: () => reduceLeft(host.getSourceFiles(), (n, s) => n + s.identifierCount, 0), + getSymbolCount: () => reduceLeft(host.getSourceFiles(), (n, s) => n + s.symbolCount, symbolCount), getTypeCount: () => typeCount, getInstantiationCount: () => totalInstantiationCount, getRelationCacheSizes: () => ({ diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 28e1c71d8c6bc..b4e261998cbd4 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -981,15 +981,6 @@ export function relativeComplement(arrayA: T[] | undefined, arrayB: T[] | und return result; } -/** @internal */ -export function sum, K extends string>(array: readonly T[], prop: K): number { - let result = 0; - for (const v of array) { - result += v[prop]; - } - return result; -} - /** * Appends a value to an array, returning the array. * From c0a9543ca36683eacf10ea26c737a2c0402245e2 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 5 Jan 2023 12:19:13 -0800 Subject: [PATCH 11/22] Call isArray directly, as it's guaranteed to exist --- src/compiler/core.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 6fafb1fbf8300..0e08c560ee9d2 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1824,7 +1824,8 @@ export function createSet(getHashCode: (element: TElem * @internal */ export function isArray(value: any): value is readonly unknown[] { - return Array.isArray ? Array.isArray(value) : value instanceof Array; + // See: https://github.com/microsoft/TypeScript/issues/17002 + return Array.isArray(value); } /** @internal */ From b96fb02ee3be3d37206c98e4fd95d516dbc8ebab Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 5 Jan 2023 12:40:01 -0800 Subject: [PATCH 12/22] Use native at when available --- src/compiler/core.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 0e08c560ee9d2..5f3e6cca0f296 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1145,22 +1145,23 @@ export function rangeEquals(array1: readonly T[], array2: readonly T[], pos: } return true; } - /** * Returns the element at a specific offset in an array if non-empty, `undefined` otherwise. * A negative offset indicates the element should be retrieved from the end of the array. * * @internal */ -export function elementAt(array: readonly T[] | undefined, offset: number): T | undefined { - if (array) { - offset = toOffset(array, offset); - if (offset < array.length) { - return array[offset]; +export const elementAt: (array: readonly T[] | undefined, offset: number) => T | undefined = !!Array.prototype.at + ? (array, offset) => array?.at(offset) + : (array, offset) => { + if (array) { + offset = toOffset(array, offset); + if (offset < array.length) { + return array[offset]; + } } - } - return undefined; -} + return undefined; + }; /** * Returns the first element of an array if non-empty, `undefined` otherwise. From 54dbc760f35449793a8f8b7de033e0e297fc6669 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 5 Jan 2023 13:23:48 -0800 Subject: [PATCH 13/22] Remove Push from public API --- src/compiler/commandLineParser.ts | 6 +++--- src/compiler/corePublic.ts | 8 ++++++-- src/compiler/utilitiesPublic.ts | 2 +- tests/baselines/reference/api/tsserverlibrary.d.ts | 8 ++------ tests/baselines/reference/api/typescript.d.ts | 8 ++------ 5 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index c4a0325c951c8..65bcc83c38819 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -2287,7 +2287,7 @@ function convertConfigFileToObject(sourceFile: JsonSourceFile, errors: Push): any { +export function convertToObject(sourceFile: JsonSourceFile, errors: Diagnostic[]): any { return convertToObjectWorker(sourceFile, sourceFile.statements[0]?.expression, errors, /*returnValue*/ true, /*knownRootOptions*/ undefined, /*jsonConversionNotifier*/ undefined); } @@ -3176,7 +3176,7 @@ function parseConfig( basePath: string, configFileName: string | undefined, resolutionStack: string[], - errors: Push, + errors: Diagnostic[], extendedConfigCache?: Map ): ParsedTsconfig { basePath = normalizeSlashes(basePath); @@ -3431,7 +3431,7 @@ function getExtendedConfig( extendedConfigPath: string, host: ParseConfigHost, resolutionStack: string[], - errors: Push, + errors: Diagnostic[], extendedConfigCache: Map | undefined, result: ExtendsResult ): ParsedTsconfig | undefined { diff --git a/src/compiler/corePublic.ts b/src/compiler/corePublic.ts index d4485e6b0302d..817df8a7587ca 100644 --- a/src/compiler/corePublic.ts +++ b/src/compiler/corePublic.ts @@ -23,10 +23,14 @@ export interface SortedArray extends Array { " __sortedArrayBrand": any; } -/** Array that is only intended to be pushed to, never read. */ +/** + * Array that is only intended to be pushed to, never read. + * + * @internal + */ export interface Push { push(...values: T[]): void; - /** @internal */ readonly length: number; + readonly length: number; } /** @internal */ diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 43a52da22f7dc..7bb784a3a57bd 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -602,7 +602,7 @@ export const supportedLocaleDirectories = ["cs", "de", "es", "fr", "it", "ja", " export function validateLocaleAndSetLanguage( locale: string, sys: { getExecutingFilePath(): string, resolvePath(path: string): string, fileExists(fileName: string): boolean, readFile(fileName: string): string | undefined }, - errors?: Push) { + errors?: Diagnostic[]) { const lowerCaseLocale = locale.toLowerCase(); const matchResult = /^([a-z]+)([_\-]([a-z]+))?$/.exec(lowerCaseLocale); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 9a9d1f7bebd7e..44e2e6143aba9 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3966,10 +3966,6 @@ declare namespace ts { interface SortedArray extends Array { " __sortedArrayBrand": any; } - /** Array that is only intended to be pushed to, never read. */ - interface Push { - push(...values: T[]): void; - } type Path = string & { __pathBrand: any; }; @@ -8558,7 +8554,7 @@ declare namespace ts { resolvePath(path: string): string; fileExists(fileName: string): boolean; readFile(fileName: string): string | undefined; - }, errors?: Push): void; + }, errors?: Diagnostic[]): void; function getOriginalNode(node: Node): Node; function getOriginalNode(node: Node, nodeTest: (node: Node) => node is T): T; function getOriginalNode(node: Node | undefined): Node | undefined; @@ -9138,7 +9134,7 @@ declare namespace ts { /** * Convert the json syntax tree into the json value */ - function convertToObject(sourceFile: JsonSourceFile, errors: Push): any; + function convertToObject(sourceFile: JsonSourceFile, errors: Diagnostic[]): any; /** * Parse the contents of a config file (tsconfig.json). * @param json The contents of the config file to parse diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 611633da9f02b..e29bb395fe5f4 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -31,10 +31,6 @@ declare namespace ts { interface SortedArray extends Array { " __sortedArrayBrand": any; } - /** Array that is only intended to be pushed to, never read. */ - interface Push { - push(...values: T[]): void; - } type Path = string & { __pathBrand: any; }; @@ -4623,7 +4619,7 @@ declare namespace ts { resolvePath(path: string): string; fileExists(fileName: string): boolean; readFile(fileName: string): string | undefined; - }, errors?: Push): void; + }, errors?: Diagnostic[]): void; function getOriginalNode(node: Node): Node; function getOriginalNode(node: Node, nodeTest: (node: Node) => node is T): T; function getOriginalNode(node: Node | undefined): Node | undefined; @@ -5203,7 +5199,7 @@ declare namespace ts { /** * Convert the json syntax tree into the json value */ - function convertToObject(sourceFile: JsonSourceFile, errors: Push): any; + function convertToObject(sourceFile: JsonSourceFile, errors: Diagnostic[]): any; /** * Parse the contents of a config file (tsconfig.json). * @param json The contents of the config file to parse From a08808eff8c355e185726726481a71afe4b9cd1e Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Fri, 6 Jan 2023 10:57:01 -0800 Subject: [PATCH 14/22] Restore arrayFrom, which is faster than Array.from, somehow --- src/compiler/builder.ts | 17 +++++----- src/compiler/builderState.ts | 7 ++-- src/compiler/checker.ts | 33 ++++++++++--------- src/compiler/commandLineParser.ts | 13 ++++---- src/compiler/core.ts | 21 ++++++++++-- src/compiler/moduleNameResolver.ts | 3 +- src/compiler/moduleSpecifiers.ts | 3 +- src/compiler/program.ts | 3 +- src/compiler/sourcemap.ts | 3 +- src/compiler/transformers/declarations.ts | 5 +-- src/compiler/transformers/jsx.ts | 7 ++-- src/compiler/utilities.ts | 3 +- src/executeCommandLine/executeCommandLine.ts | 3 +- src/harness/compilerImpl.ts | 2 +- src/harness/documentsUtil.ts | 4 +-- src/harness/fourslashImpl.ts | 16 ++++----- src/harness/harnessIO.ts | 6 ++-- src/harness/vfsUtil.ts | 4 +-- src/server/editorServices.ts | 18 +++++----- src/server/project.ts | 9 ++--- src/server/session.ts | 7 ++-- src/services/codeFixProvider.ts | 3 +- src/services/codefixes/convertToEsModule.ts | 5 +-- src/services/codefixes/fixAddMissingMember.ts | 5 +-- src/services/codefixes/helpers.ts | 5 +-- src/services/codefixes/importFixes.ts | 7 ++-- src/services/documentHighlights.ts | 3 +- src/services/documentRegistry.ts | 5 +-- src/services/refactorProvider.ts | 3 +- src/services/refactors/convertImport.ts | 3 +- src/services/refactors/extractSymbol.ts | 3 +- src/services/stringCompletions.ts | 9 ++--- src/services/symbolDisplay.ts | 3 +- src/testRunner/test262Runner.ts | 4 +-- src/testRunner/unittests/compilerCore.ts | 6 ++-- src/testRunner/unittests/customTransforms.ts | 4 +-- src/testRunner/unittests/programApi.ts | 2 +- src/testRunner/unittests/tsc/helpers.ts | 4 +-- .../unittests/tscWatch/incremental.ts | 4 +-- src/testRunner/unittests/tsserver/helpers.ts | 2 +- 40 files changed, 156 insertions(+), 111 deletions(-) diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 4b7274bffac8c..2bfb44b9e7abb 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -2,6 +2,7 @@ import * as ts from "./_namespaces/ts"; import { addRange, AffectedFileResult, + arrayFrom, arrayToMap, BuilderProgram, BuilderProgramHost, @@ -966,7 +967,7 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde if (outFile(state.compilerOptions)) { // Copy all fileInfo, version and impliedFormat // Affects global scope and signature doesnt matter because with --out they arent calculated or needed to determine upto date ness - const fileInfos = Array.from(state.fileInfos.entries(), ([key, value]): ProgramBundleEmitBuildInfoFileInfo => { + const fileInfos = arrayFrom(state.fileInfos.entries(), ([key, value]): ProgramBundleEmitBuildInfoFileInfo => { // Ensure fileId toFileId(key); return value.impliedFormat ? @@ -999,7 +1000,7 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde let fileIdsList: (readonly ProgramBuildInfoFileId[])[] | undefined; let fileNamesToFileIdListId: Map | undefined; let emitSignatures: ProgramBuildInfoEmitSignature[] | undefined; - const fileInfos = Array.from(state.fileInfos.entries(), ([key, value]): ProgramMultiFileEmitBuildInfoFileInfo => { + const fileInfos = arrayFrom(state.fileInfos.entries(), ([key, value]): ProgramMultiFileEmitBuildInfoFileInfo => { // Ensure fileId const fileId = toFileId(key); Debug.assert(fileNames[fileId - 1] === relativeToBuildInfo(key)); @@ -1035,7 +1036,7 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde let referencedMap: ProgramBuildInfoReferencedMap | undefined; if (state.referencedMap) { - referencedMap = Array.from(state.referencedMap.keys()).sort(compareStringsCaseSensitive).map(key => [ + referencedMap = arrayFrom(state.referencedMap.keys()).sort(compareStringsCaseSensitive).map(key => [ toFileId(key), toFileIdListId(state.referencedMap!.getValues(key)!) ]); @@ -1043,7 +1044,7 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde let exportedModulesMap: ProgramBuildInfoReferencedMap | undefined; if (state.exportedModulesMap) { - exportedModulesMap = mapDefined(Array.from(state.exportedModulesMap.keys()).sort(compareStringsCaseSensitive), key => { + exportedModulesMap = mapDefined(arrayFrom(state.exportedModulesMap.keys()).sort(compareStringsCaseSensitive), key => { const oldValue = state.oldExportedModulesMap?.get(key); // Not in temporary cache, use existing value if (oldValue === undefined) return [toFileId(key), toFileIdListId(state.exportedModulesMap!.getValues(key)!)]; @@ -1054,7 +1055,7 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde let semanticDiagnosticsPerFile: ProgramBuildInfoDiagnostic[] | undefined; if (state.semanticDiagnosticsPerFile) { - for (const key of Array.from(state.semanticDiagnosticsPerFile.keys()).sort(compareStringsCaseSensitive)) { + for (const key of arrayFrom(state.semanticDiagnosticsPerFile.keys()).sort(compareStringsCaseSensitive)) { const value = state.semanticDiagnosticsPerFile.get(key)!; (semanticDiagnosticsPerFile ||= []).push( value.length ? @@ -1071,7 +1072,7 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde if (state.affectedFilesPendingEmit?.size) { const fullEmitForOptions = getBuilderFileEmit(state.compilerOptions); const seenFiles = new Set(); - for (const path of Array.from(state.affectedFilesPendingEmit.keys()).sort(compareStringsCaseSensitive)) { + for (const path of arrayFrom(state.affectedFilesPendingEmit.keys()).sort(compareStringsCaseSensitive)) { if (tryAddToSet(seenFiles, path)) { const file = state.program!.getSourceFileByPath(path); if (!file || !sourceFileMayBeEmitted(file, state.program!)) continue; @@ -1089,7 +1090,7 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde let changeFileSet: ProgramBuildInfoFileId[] | undefined; if (state.changedFilesSet.size) { - for (const path of Array.from(state.changedFilesSet.keys()).sort(compareStringsCaseSensitive)) { + for (const path of arrayFrom(state.changedFilesSet.keys()).sort(compareStringsCaseSensitive)) { (changeFileSet ||= []).push(toFileId(path)); } } @@ -1127,7 +1128,7 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde } function toFileIdListId(set: ReadonlySet): ProgramBuildInfoFileIdListId { - const fileIds = Array.from(set.keys(), toFileId).sort(compareValues); + const fileIds = arrayFrom(set.keys(), toFileId).sort(compareValues); const key = fileIds.join(); let fileIdListId = fileNamesToFileIdListId?.get(key); if (fileIdListId === undefined) { diff --git a/src/compiler/builderState.ts b/src/compiler/builderState.ts index 638a78f320cce..aae94e1b4c851 100644 --- a/src/compiler/builderState.ts +++ b/src/compiler/builderState.ts @@ -1,4 +1,5 @@ import { + arrayFrom, CancellationToken, computeSignatureWithDiagnostics, CustomTransformers, @@ -525,7 +526,7 @@ export namespace BuilderState { } } - return Array.from(mapDefinedIterator(seenMap.keys(), path => programOfThisState.getSourceFileByPath(path)?.fileName ?? path)); + return arrayFrom(mapDefinedIterator(seenMap.keys(), path => programOfThisState.getSourceFileByPath(path)?.fileName ?? path)); } /** @@ -544,7 +545,7 @@ export namespace BuilderState { */ export function getReferencedByPaths(state: Readonly, referencedFilePath: Path) { const keys = state.referencedMap!.getKeys(referencedFilePath); - return keys ? Array.from(keys.keys()) : []; + return keys ? arrayFrom(keys.keys()) : []; } /** @@ -656,6 +657,6 @@ export namespace BuilderState { } // Return array of values that needs emit - return Array.from(mapDefinedIterator(seenFileNamesMap.values(), value => value)); + return arrayFrom(mapDefinedIterator(seenFileNamesMap.values(), value => value)); } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b4c0cc42249ec..f0fc253c145ee 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16,6 +16,7 @@ import { append, appendIfUnique, ArrayBindingPattern, + arrayFrom, arrayIsHomogeneous, ArrayLiteralExpression, arrayOf, @@ -346,8 +347,8 @@ import { hasAccessorModifier, hasAmbientModifier, hasContextSensitiveParameters, - hasDecorators, HasDecorators, + hasDecorators, hasDynamicName, hasEffectiveModifier, hasEffectiveModifiers, @@ -356,8 +357,8 @@ import { hasExtension, HasIllegalDecorators, HasIllegalModifiers, - hasInitializer, HasInitializer, + hasInitializer, hasJSDocNodes, hasJSDocParameterTags, hasJsonModuleEmitEnabled, @@ -2545,7 +2546,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (mainModule.exports?.get(InternalSymbolName.ExportStar) && moduleAugmentation.symbol.exports?.size) { // We may need to merge the module augmentation's exports into the target symbols of the resolved exports const resolvedExports = getResolvedMembersOrExportsOfSymbol(mainModule, MembersOrExportsResolutionKind.resolvedExports); - for (const [key, value] of Array.from(moduleAugmentation.symbol.exports.entries())) { + for (const [key, value] of arrayFrom(moduleAugmentation.symbol.exports.entries())) { if (resolvedExports.has(key) && !mainModule.exports.has(key)) { mergeSymbol(resolvedExports.get(key)!, value); } @@ -5456,7 +5457,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function createTypeofType() { - return getUnionType(Array.from(typeofNEFacts.keys(), getStringLiteralType)); + return getUnionType(arrayFrom(typeofNEFacts.keys(), getStringLiteralType)); } function createTypeParameter(symbol?: Symbol) { @@ -8616,7 +8617,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getNamespaceMembersForSerialization(symbol: Symbol) { - return !symbol.exports ? [] : filter(Array.from(symbol.exports.values()), isNamespaceMember); + return !symbol.exports ? [] : filter(arrayFrom(symbol.exports.values()), isNamespaceMember); } function isTypeOnlyNamespace(symbol: Symbol) { @@ -12135,7 +12136,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const assignments = symbol.assignmentDeclarationMembers; if (assignments) { - const decls = Array.from(assignments.values()); + const decls = arrayFrom(assignments.values()); for (const member of decls) { const assignmentKind = getAssignmentDeclarationKind(member as BinaryExpression | CallExpression); const isInstanceMember = assignmentKind === AssignmentDeclarationKind.PrototypeProperty @@ -13192,7 +13193,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } - return Array.from(props.values()); + return arrayFrom(props.values()); } function getConstraintOfType(type: InstantiableType | UnionOrIntersectionType): Type | undefined { @@ -13669,7 +13670,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return singleProp; } } - const props = propSet ? Array.from(propSet.values()) : [singleProp]; + const props = propSet ? arrayFrom(propSet.values()) : [singleProp]; let declarations: Declaration[] | undefined; let firstType: Type | undefined; let nameType: Type | undefined; @@ -16281,7 +16282,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getIntersectionType(types: readonly Type[], aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[], noSupertypeReduction?: boolean): Type { const typeMembershipMap: Map = new Map(); const includes = addTypesToIntersection(typeMembershipMap, 0 as TypeFlags, types); - const typeSet: Type[] = Array.from(typeMembershipMap.values()); + const typeSet: Type[] = arrayFrom(typeMembershipMap.values()); // An intersection type is considered empty if it contains // the type never, or // more than one unit type or, @@ -21520,7 +21521,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } } - const props = Array.from(getUnmatchedProperties(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false)); + const props = arrayFrom(getUnmatchedProperties(source, target, requireOptionalProperties, /*matchDiscriminantProperties*/ false)); if (!headMessage || (headMessage.code !== Diagnostics.Class_0_incorrectly_implements_interface_1.code && headMessage.code !== Diagnostics.Class_0_incorrectly_implements_class_1_Did_you_mean_to_extend_1_and_inherit_its_members_as_a_subclass.code)) { shouldSkipElaboration = true; // Retain top-level error for interface implementing issues, otherwise omit it @@ -22980,7 +22981,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } - context.resolvedProperties = Array.from(names.values()); + context.resolvedProperties = arrayFrom(names.values()); } return context.resolvedProperties; } @@ -31060,10 +31061,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { s => symbols.has((s.charAt(0).toUpperCase() + s.slice(1)) as __String) ? createSymbol(SymbolFlags.TypeAlias, s as __String) as Symbol : undefined); - candidates = primitives.concat(Array.from(symbols.values())); + candidates = primitives.concat(arrayFrom(symbols.values())); } else { - candidates = Array.from(symbols.values()); + candidates = arrayFrom(symbols.values()); } return getSpellingSuggestionForName(unescapeLeadingUnderscores(name), candidates, meaning); }); @@ -41918,7 +41919,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - return Array.from(seen.values()); + return arrayFrom(seen.values()); } function checkInheritedPropertiesAreIdentical(type: InterfaceType, typeNode: Node): boolean { @@ -45122,7 +45123,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!importTarget) return false; if (importTarget === file) return false; const exports = getExportsOfModule(file.symbol); - for (const s of Array.from(exports.values())) { + for (const s of arrayFrom(exports.values())) { if (s.mergeId) { const merged = getMergedSymbol(s); if (merged.declarations) { @@ -45365,7 +45366,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { // Otherwise issue top-level error since the files appear very identical in terms of what they contain - const list = Array.from(conflictingSymbols.keys()).join(", "); + const list = arrayFrom(conflictingSymbols.keys()).join(", "); diagnostics.add(addRelatedInfo( createDiagnosticForNode(firstFile, Diagnostics.Definitions_of_the_following_identifiers_conflict_with_those_in_another_file_Colon_0, list), createDiagnosticForNode(secondFile, Diagnostics.Conflicts_are_in_this_file) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 65bcc83c38819..1010bd171c63a 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1,6 +1,7 @@ import { AlternateModeDiagnostics, append, + arrayFrom, ArrayLiteralExpression, arrayToMap, assign, @@ -1693,7 +1694,7 @@ export function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOpt } function createDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType, createDiagnostic: (message: DiagnosticMessage, arg0: string, arg1: string) => Diagnostic): Diagnostic { - const namesOfType = Array.from(opt.type.keys()); + const namesOfType = arrayFrom(opt.type.keys()); const stringNames = (opt.deprecatedKeys ? namesOfType.filter(k => !opt.deprecatedKeys!.has(k)) : namesOfType).map(key => `'${key}'`).join(", "); return createDiagnostic(Diagnostics.Argument_for_0_option_must_be_Colon_1, `--${opt.name}`, stringNames); } @@ -2599,7 +2600,7 @@ export function convertToTSConfig(configParseResult: ParsedCommandLine, configFi /** @internal */ export function optionMapToObject(optionMap: Map): object { return { - ...Array.from(optionMap.entries()).reduce((prev, cur) => ({ ...prev, [cur[0]]: cur[1] }), {}), + ...arrayFrom(optionMap.entries()).reduce((prev, cur) => ({ ...prev, [cur[0]]: cur[1] }), {}), }; } @@ -3212,7 +3213,7 @@ function parseConfig( if (!ownConfig.raw.exclude && result.exclude) ownConfig.raw.exclude = result.exclude; if (!ownConfig.raw.files && result.files) ownConfig.raw.files = result.files; if (ownConfig.raw.compileOnSave === undefined && result.compileOnSave) ownConfig.raw.compileOnSave = result.compileOnSave; - if (sourceFile && result.extendedSourceFiles) sourceFile.extendedSourceFiles = Array.from(result.extendedSourceFiles.keys()); + if (sourceFile && result.extendedSourceFiles) sourceFile.extendedSourceFiles = arrayFrom(result.extendedSourceFiles.keys()); ownConfig.options = assign(result.options, ownConfig.options); ownConfig.watchOptions = ownConfig.watchOptions && result.watchOptions ? @@ -3740,10 +3741,10 @@ export function getFileNamesFromConfigSpecs( } } - const literalFiles = Array.from(literalFileMap.values()); - const wildcardFiles = Array.from(wildcardFileMap.values()); + const literalFiles = arrayFrom(literalFileMap.values()); + const wildcardFiles = arrayFrom(wildcardFileMap.values()); - return literalFiles.concat(wildcardFiles, Array.from(wildCardJsonFileMap.values())); + return literalFiles.concat(wildcardFiles, arrayFrom(wildCardJsonFileMap.values())); } /** @internal */ diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 5f3e6cca0f296..078b5810d947c 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1416,6 +1416,23 @@ export function arrayOf(count: number, f: (index: number) => T): T[] { return result; } +/** + * Shims `Array.from`. + * + * @internal + */ +export function arrayFrom(iterator: Iterable, map: (t: T) => U): U[]; +/** @internal */ +export function arrayFrom(iterator: Iterable): T[]; +/** @internal */ +export function arrayFrom(iterator: Iterable, map?: (t: T) => U): (T | U)[] { + const result: (T | U)[] = []; + for (const value of iterator) { + result.push(map ? map(value) : value); + } + return result; +} + /** @internal */ export function assign(t: T, ...args: (T | undefined)[]) { for (const arg of args) { @@ -1521,7 +1538,7 @@ export function group(values: readonly T[], getGroupId: (value: T) => string) export function group(values: readonly T[], getGroupId: (value: T) => string, resultSelector: (values: readonly T[]) => R): R[]; /** @internal */ export function group(values: readonly T[], getGroupId: (value: T) => K, resultSelector: (values: readonly T[]) => readonly T[] = identity): readonly (readonly T[])[] { - return Array.from(arrayToMultiMap(values, getGroupId).values(), resultSelector); + return arrayFrom(arrayToMultiMap(values, getGroupId).values(), resultSelector); } /** @internal */ @@ -1787,7 +1804,7 @@ export function createSet(getHashCode: (element: TElem return size; }, forEach(action: (value: TElement, key: TElement, set: Set) => void): void { - for (const elements of Array.from(multiMap.values())) { + for (const elements of arrayFrom(multiMap.values())) { if (isArray(elements)) { for (const element of elements) { action(element, element, set); diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 72f162af8555f..be8573b075db3 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -1,6 +1,7 @@ import { append, appendIfUnique, + arrayFrom, arrayIsEqualTo, changeAnyExtension, CharacterCodes, @@ -922,7 +923,7 @@ function createPackageJsonInfoCache(currentDirectory: string, getCanonicalFileNa } function entries() { const iter = cache?.entries(); - return iter ? Array.from(iter) : []; + return iter ? arrayFrom(iter) : []; } function getInternalMap() { return cache; diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts index e50da231c6a83..351d98a24bd19 100644 --- a/src/compiler/moduleSpecifiers.ts +++ b/src/compiler/moduleSpecifiers.ts @@ -3,6 +3,7 @@ import { allKeysStartWithDot, AmbientModuleDeclaration, append, + arrayFrom, CharacterCodes, combinePaths, compareBooleans, @@ -645,7 +646,7 @@ function getAllModulePathsWorker(importingFileName: Path, importedFileName: stri directory = newDirectory; } if (allFileNames.size) { - const remainingPaths = Array.from(allFileNames.values()); + const remainingPaths = arrayFrom(allFileNames.values()); if (remainingPaths.length > 1) remainingPaths.sort(comparePathsByRedirectAndNumberOfDirectorySeparators); sortedPaths.push(...remainingPaths); } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index cfc96686be260..a9ac7f940e220 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -4,6 +4,7 @@ import { addEmitFlags, addRange, append, + arrayFrom, arrayIsEqualTo, AsExpression, AssertClause, @@ -1709,7 +1710,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } } - missingFilePaths = Array.from(mapDefinedIterator(filesByName.entries(), ([path, file]) => file === undefined ? path as Path : undefined)); + missingFilePaths = arrayFrom(mapDefinedIterator(filesByName.entries(), ([path, file]) => file === undefined ? path as Path : undefined)); files = stableSort(processingDefaultLibFiles, compareDefaultLibFiles).concat(processingOtherFiles); processingDefaultLibFiles = undefined; processingOtherFiles = undefined; diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index fa8ffc896fadb..8b5126d53e5c8 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -1,4 +1,5 @@ import { + arrayFrom, binarySearchKey, CharacterCodes, combinePaths, @@ -723,7 +724,7 @@ export function createDocumentPositionMapper(host: DocumentPositionMapperHost, m function getDecodedMappings() { if (decodedMappings === undefined) { const decoder = decodeMappings(map.mappings); - const mappings = Array.from(decoder, processMapping); + const mappings = arrayFrom(decoder, processMapping); if (decoder.error !== undefined) { if (host.log) { host.log(`Encountered error while decoding sourcemap: ${decoder.error}`); diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index a01077f85ccee..cce16221d24c4 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -5,6 +5,7 @@ import { AnyImportSyntax, append, ArrayBindingElement, + arrayFrom, AssertClause, BindingElement, BindingName, @@ -572,11 +573,11 @@ export function transformDeclarations(context: TransformationContext) { return updated; function getLibReferences() { - return Array.from(libs.keys(), lib => ({ fileName: lib, pos: -1, end: -1 })); + return arrayFrom(libs.keys(), lib => ({ fileName: lib, pos: -1, end: -1 })); } function getFileReferencesForUsedTypeReferences() { - return necessaryTypeReferences ? mapDefined(Array.from(necessaryTypeReferences.keys()), getFileReferenceForSpecifierModeTuple) : []; + return necessaryTypeReferences ? mapDefined(arrayFrom(necessaryTypeReferences.keys()), getFileReferenceForSpecifierModeTuple) : []; } function getFileReferenceForSpecifierModeTuple([typeName, mode]: [specifier: string, mode: ResolutionMode]): FileReference | undefined { diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index c6e8ac6193aa5..572ed1c594eac 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -1,5 +1,6 @@ import { addEmitHelpers, + arrayFrom, Bundle, chainBundle, createExpressionForJsxElement, @@ -159,10 +160,10 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B statements = insertStatementAfterCustomPrologue(statements.slice(), factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([currentFileState.filenameDeclaration], NodeFlags.Const))); } if (currentFileState.utilizedImplicitRuntimeImports) { - for (const [importSource, importSpecifiersMap] of Array.from(currentFileState.utilizedImplicitRuntimeImports.entries())) { + for (const [importSource, importSpecifiersMap] of arrayFrom(currentFileState.utilizedImplicitRuntimeImports.entries())) { if (isExternalModule(node)) { // Add `import` statement - const importStatement = factory.createImportDeclaration(/*modifiers*/ undefined, factory.createImportClause(/*typeOnly*/ false, /*name*/ undefined, factory.createNamedImports(Array.from(importSpecifiersMap.values()))), factory.createStringLiteral(importSource), /*assertClause*/ undefined); + const importStatement = factory.createImportDeclaration(/*modifiers*/ undefined, factory.createImportClause(/*typeOnly*/ false, /*name*/ undefined, factory.createNamedImports(arrayFrom(importSpecifiersMap.values()))), factory.createStringLiteral(importSource), /*assertClause*/ undefined); setParentRecursive(importStatement, /*incremental*/ false); statements = insertStatementAfterCustomPrologue(statements.slice(), importStatement); } @@ -170,7 +171,7 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B // Add `require` statement const requireStatement = factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([ factory.createVariableDeclaration( - factory.createObjectBindingPattern(Array.from(importSpecifiersMap.values(), s => factory.createBindingElement(/*dotdotdot*/ undefined, s.propertyName, s.name))), + factory.createObjectBindingPattern(arrayFrom(importSpecifiersMap.values(), s => factory.createBindingElement(/*dotdotdot*/ undefined, s.propertyName, s.name))), /*exclaimationToken*/ undefined, /*type*/ undefined, factory.createCallExpression(factory.createIdentifier("require"), /*typeArguments*/ undefined, [factory.createStringLiteral(importSource)]) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 90f71e2d20df2..c339ea058ba60 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -12,6 +12,7 @@ import { AnyImportSyntax, AnyValidImportOrReExport, append, + arrayFrom, ArrayLiteralExpression, ArrayTypeNode, ArrowFunction, @@ -1049,7 +1050,7 @@ export function createCommentDirectivesMap(sourceFile: SourceFile, commentDirect return { getUnusedExpectations, markUsed }; function getUnusedExpectations() { - return Array.from(directivesByLine.entries()) + return arrayFrom(directivesByLine.entries()) .filter(([line, directive]) => directive.type === CommentDirectiveType.ExpectError && !usedLines.get(line)) .map(([_, directive]) => directive); } diff --git a/src/executeCommandLine/executeCommandLine.ts b/src/executeCommandLine/executeCommandLine.ts index 9ee87060e48db..2b4c71c45cfd3 100644 --- a/src/executeCommandLine/executeCommandLine.ts +++ b/src/executeCommandLine/executeCommandLine.ts @@ -1,5 +1,6 @@ import * as ts from "./_namespaces/ts"; import { + arrayFrom, BuilderProgram, BuildOptions, buildOpts, @@ -302,7 +303,7 @@ function generateOptionOutput(sys: System, option: CommandLineOption, rightAlign ) { return defaultValue !== undefined && typeof type === "object" // e.g. ScriptTarget.ES2015 -> "es6/es2015" - ? Array.from(type.entries()) + ? arrayFrom(type.entries()) .filter(([, value]) => value === defaultValue) .map(([name]) => name) .join("/") diff --git a/src/harness/compilerImpl.ts b/src/harness/compilerImpl.ts index 7b7288e2b914e..6897adcc8b92c 100644 --- a/src/harness/compilerImpl.ts +++ b/src/harness/compilerImpl.ts @@ -191,7 +191,7 @@ export class CompilationResult { public getSourceMapRecord(): string | undefined { const maps = this.result!.sourceMaps; if (maps && maps.length > 0) { - return Harness.SourceMapRecorder.getSourceMapRecord(maps, this.program!, Array.from(this.js.values()).filter(d => !ts.fileExtensionIs(d.file, ts.Extension.Json)), Array.from(this.dts.values())); + return Harness.SourceMapRecorder.getSourceMapRecord(maps, this.program!, ts.arrayFrom(this.js.values()).filter(d => !ts.fileExtensionIs(d.file, ts.Extension.Json)), ts.arrayFrom(this.dts.values())); } } diff --git a/src/harness/documentsUtil.ts b/src/harness/documentsUtil.ts index dd012f4477263..fa00ff2d06213 100644 --- a/src/harness/documentsUtil.ts +++ b/src/harness/documentsUtil.ts @@ -34,7 +34,7 @@ export class TextDocument { return this._testFile || (this._testFile = { unitName: this.file, content: this.text, - fileOptions: Array.from(this.meta) + fileOptions: ts.arrayFrom(this.meta) .reduce((obj, [key, value]) => (obj[key] = value, obj), {} as Record) }); } @@ -185,4 +185,4 @@ export class SourceMap { } return vlq; } -} \ No newline at end of file +} diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 81f9a9f526df8..ee0e6e599eb25 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -1965,7 +1965,7 @@ export class TestState { public baselineQuickInfo() { const baselineFile = this.getBaselineFileNameForContainingTestFile(); - const result = Array.from(this.testData.markerPositions.entries(), ([name, marker]) => ({ + const result = ts.arrayFrom(this.testData.markerPositions.entries(), ([name, marker]) => ({ marker: { ...marker, name }, quickInfo: this.languageService.getQuickInfoAtPosition(marker.fileName, marker.position) })); @@ -1974,7 +1974,7 @@ export class TestState { public baselineSignatureHelp() { const baselineFile = this.getBaselineFileNameForContainingTestFile(); - const result = Array.from(this.testData.markerPositions.entries(), ([name, marker]) => ({ + const result = ts.arrayFrom(this.testData.markerPositions.entries(), ([name, marker]) => ({ marker: { ...marker, name }, signatureHelp: this.languageService.getSignatureHelpItems(marker.fileName, marker.position, /*options*/ undefined) })); @@ -1983,7 +1983,7 @@ export class TestState { public baselineCompletions(preferences?: ts.UserPreferences) { const baselineFile = this.getBaselineFileNameForContainingTestFile(); - const result = Array.from(this.testData.markerPositions.entries(), ([name, marker]) => { + const result = ts.arrayFrom(this.testData.markerPositions.entries(), ([name, marker]) => { this.goToMarker(marker); const completions = this.getCompletionListAtCaret(preferences); return { @@ -2010,7 +2010,7 @@ export class TestState { let selectionRange: ts.SelectionRange | undefined = this.languageService.getSmartSelectionRange(this.activeFile.fileName, marker.position); while (selectionRange) { const { textSpan } = selectionRange; - let masked = Array.from(fileContent).map((char, index) => { + let masked = ts.arrayFrom(fileContent).map((char, index) => { const charCode = char.charCodeAt(0); if (index >= textSpan.start && index < ts.textSpanEnd(textSpan)) { return char === " " ? "•" : ts.isLineBreak(charCode) ? `↲${n}` : char; @@ -2019,8 +2019,8 @@ export class TestState { }).join(""); masked = masked.replace(/^\s*$\r?\n?/gm, ""); // Remove blank lines const isRealCharacter = (char: string) => char !== "•" && char !== "↲" && !ts.isWhiteSpaceLike(char.charCodeAt(0)); - const leadingWidth = Array.from(masked).findIndex(isRealCharacter); - const trailingWidth = ts.findLastIndex(Array.from(masked), isRealCharacter); + const leadingWidth = ts.arrayFrom(masked).findIndex(isRealCharacter); + const trailingWidth = ts.findLastIndex(ts.arrayFrom(masked), isRealCharacter); masked = masked.slice(0, leadingWidth) + masked.slice(leadingWidth, trailingWidth).replace(/•/g, " ").replace(/↲/g, "") + masked.slice(trailingWidth); @@ -2526,7 +2526,7 @@ export class TestState { } public getMarkerNames(): string[] { - return Array.from(this.testData.markerPositions.keys()); + return ts.arrayFrom(this.testData.markerPositions.keys()); } public getRanges(): Range[] { @@ -4598,7 +4598,7 @@ function unique(inputs: readonly T[], getOutput: (t: T) => string): string[] const out = getOutput(input); set.set(out, true); } - return Array.from(set.keys()); + return ts.arrayFrom(set.keys()); } function toArray(x: ArrayOrSingle): readonly T[] { diff --git a/src/harness/harnessIO.ts b/src/harness/harnessIO.ts index 9add3b76f7517..eb2f984f3f874 100644 --- a/src/harness/harnessIO.ts +++ b/src/harness/harnessIO.ts @@ -964,7 +964,7 @@ export namespace Compiler { export function* iterateOutputs(outputFiles: Iterable): IterableIterator<[string, string]> { // Collect, test, and sort the fileNames - const files = Array.from(outputFiles); + const files = ts.arrayFrom(outputFiles); files.slice().sort((a, b) => ts.compareStringsCaseSensitive(cleanName(a.file), cleanName(b.file))); const dupeCase = new Map(); // Yield them @@ -1048,7 +1048,7 @@ function splitVaryBySettingValue(text: string, varyBy: string): string[] | undef if (star && values) { // add all entries - for (const [key, value] of Array.from(values.entries())) { + for (const [key, value] of ts.arrayFrom(values.entries())) { if (ts.findIndex(variations, v => v.key === key || v.value === value) === -1) { variations.push({ key, value }); } @@ -1482,7 +1482,7 @@ export namespace Baseline { errorMsg += "\n"; } if (missing.length) { - const writtenFilesArray = Array.from(writtenFiles.keys()); + const writtenFilesArray = ts.arrayFrom(writtenFiles.keys()); errorMsg += `Baseline missing ${missing.length} files:${"\n " + missing.slice(0, 5).join("\n ") + (missing.length > 5 ? "\n" + ` and ${missing.length - 5} more` : "") + "\n"}Written ${writtenFiles.size} files:${"\n " + writtenFilesArray.slice(0, 5).join("\n ") + (writtenFilesArray.length > 5 ? "\n" + ` and ${writtenFilesArray.length - 5} more` : "")}`; } throw new Error(errorMsg); diff --git a/src/harness/vfsUtil.ts b/src/harness/vfsUtil.ts index 5b8d61e0445f6..9359e93bb4859 100644 --- a/src/harness/vfsUtil.ts +++ b/src/harness/vfsUtil.ts @@ -486,7 +486,7 @@ export class FileSystem { const { node } = this._walk(this._resolve(path)); if (!node) throw createIOError("ENOENT"); if (!isDirectory(node)) throw createIOError("ENOTDIR"); - return Array.from(this._getLinks(node).keys()); + return ts.arrayFrom(this._getLinks(node).keys()); } /** @@ -1606,7 +1606,7 @@ function* iteratePatchWorker(dirname: string, container: FileSet): IterableItera const file = dirname ? vpath.combine(dirname, name) : name; if (entry instanceof Directory) { // TODO(jakebailey): redundant? - yield* Array.from(iteratePatchWorker(file, entry.files)); + yield* ts.arrayFrom(iteratePatchWorker(file, entry.files)); } else if (entry instanceof File) { const content = typeof entry.data === "string" ? entry.data : entry.data.toString("utf8"); diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index f639d67592970..8668a1986ee6c 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -49,6 +49,8 @@ import { import { addToSeen, + arrayFrom, + arrayToMap, AssertionLevel, CachedDirectoryStructureHost, @@ -1210,7 +1212,7 @@ export class ProjectService { const event: ProjectsUpdatedInBackgroundEvent = { eventName: ProjectsUpdatedInBackgroundEvent, data: { - openFiles: Array.from(this.openFiles.keys(), path => this.getScriptInfoForPath(path as Path)!.fileName) + openFiles: arrayFrom(this.openFiles.keys(), path => this.getScriptInfoForPath(path as Path)!.fileName) } }; this.eventHandler(event); @@ -1641,7 +1643,7 @@ export class ProjectService { !info.isAttached(project), "Found script Info still attached to project", () => `${project.projectName}: ScriptInfos still attached: ${JSON.stringify( - Array.from( + arrayFrom( mapDefinedIterator( this.filenameToScriptInfo.values(), info => info.isAttached(project) ? @@ -2781,7 +2783,7 @@ export class ProjectService { /** @internal */ logErrorForScriptInfoNotFound(fileName: string): void { - const names = Array.from(this.filenameToScriptInfo.entries(), ([path, scriptInfo]) => ({ path, fileName: scriptInfo.fileName })); + const names = arrayFrom(this.filenameToScriptInfo.entries(), ([path, scriptInfo]) => ({ path, fileName: scriptInfo.fileName })); this.logger.msg(`Could not find file ${JSON.stringify(fileName)}.\nAll files are: ${JSON.stringify(names)}`, Msg.Err); } @@ -2989,9 +2991,9 @@ export class ProjectService { let info = this.getScriptInfoForPath(path); if (!info) { const isDynamic = isDynamicFileName(fileName); - Debug.assert(isRootedDiskPath(fileName) || isDynamic || openedByClient, "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: Array.from(this.openFilesWithNonRootedDiskPath.keys()) })}\nScript info with non-dynamic relative file name can only be open script info or in context of host currentDirectory`); - Debug.assert(!isRootedDiskPath(fileName) || this.currentDirectory === currentDirectory || !this.openFilesWithNonRootedDiskPath.has(this.toCanonicalFileName(fileName)), "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: Array.from(this.openFilesWithNonRootedDiskPath.keys()) })}\nOpen script files with non rooted disk path opened with current directory context cannot have same canonical names`); - Debug.assert(!isDynamic || this.currentDirectory === currentDirectory || this.useInferredProjectPerProjectRoot, "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: Array.from(this.openFilesWithNonRootedDiskPath.keys()) })}\nDynamic files must always be opened with service's current directory or service should support inferred project per projectRootPath.`); + Debug.assert(isRootedDiskPath(fileName) || isDynamic || openedByClient, "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: arrayFrom(this.openFilesWithNonRootedDiskPath.keys()) })}\nScript info with non-dynamic relative file name can only be open script info or in context of host currentDirectory`); + Debug.assert(!isRootedDiskPath(fileName) || this.currentDirectory === currentDirectory || !this.openFilesWithNonRootedDiskPath.has(this.toCanonicalFileName(fileName)), "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: arrayFrom(this.openFilesWithNonRootedDiskPath.keys()) })}\nOpen script files with non rooted disk path opened with current directory context cannot have same canonical names`); + Debug.assert(!isDynamic || this.currentDirectory === currentDirectory || this.useInferredProjectPerProjectRoot, "", () => `${JSON.stringify({ fileName, currentDirectory, hostCurrentDirectory: this.currentDirectory, openKeys: arrayFrom(this.openFilesWithNonRootedDiskPath.keys()) })}\nDynamic files must always be opened with service's current directory or service should support inferred project per projectRootPath.`); // If the file is not opened by client and the file doesnot exist on the disk, return if (!openedByClient && !isDynamic && !(hostToQueryFileExistsOn || this.host).fileExists(fileName)) { return; @@ -3674,7 +3676,7 @@ export class ProjectService { const seenProjects = new Set(); // Work on array copy as we could add more projects as part of callback - for (const project of Array.from(this.configuredProjects.values())) { + for (const project of arrayFrom(this.configuredProjects.values())) { // If this project has potential project reference for any of the project we are loading ancestor tree for // load this project first if (forEachPotentialProjectReference(project, potentialRefPath => forProjects!.has(potentialRefPath))) { @@ -4329,7 +4331,7 @@ export class ProjectService { } // Consume the pending plugin enablement requests - const entries = Array.from(this.pendingPluginEnablements.entries()); + const entries = arrayFrom(this.pendingPluginEnablements.entries()); this.pendingPluginEnablements = undefined; // Start processing the requests, keeping track of the promise for the operation so that diff --git a/src/server/project.ts b/src/server/project.ts index ec6c88368e824..ab2a5252cd749 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -26,6 +26,7 @@ import { addRange, append, ApplyCodeActionCommandResult, + arrayFrom, arrayToMap, BuilderState, CachedDirectoryStructureHost, @@ -1654,11 +1655,11 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo getChangesSinceVersion(lastKnownVersion?: number, includeProjectReferenceRedirectInfo?: boolean): ProjectFilesWithTSDiagnostics { const includeProjectReferenceRedirectInfoIfRequested = includeProjectReferenceRedirectInfo - ? (files: Map) => Array.from(files.entries(), ([fileName, isSourceOfProjectReferenceRedirect]): protocol.FileWithProjectReferenceRedirectInfo => ({ + ? (files: Map) => arrayFrom(files.entries(), ([fileName, isSourceOfProjectReferenceRedirect]): protocol.FileWithProjectReferenceRedirectInfo => ({ fileName, isSourceOfProjectReferenceRedirect })) - : (files: Map) => Array.from(files.keys()); + : (files: Map) => arrayFrom(files.keys()); // Update the graph only if initial configured project load is not pending if (!this.isInitialLoadPending()) { @@ -1696,7 +1697,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo const added: Map = new Map(); const removed: Map = new Map(); - const updated: string[] = updatedFileNames ? Array.from(updatedFileNames.keys()) : []; + const updated: string[] = updatedFileNames ? arrayFrom(updatedFileNames.keys()) : []; const updatedRedirects: protocol.FileWithProjectReferenceRedirectInfo[] = []; forEachEntry(currentFiles, (isSourceOfProjectReferenceRedirect, fileName) => { @@ -2279,7 +2280,7 @@ export class AutoImportProviderProject extends Project { let dependenciesAdded = 0; if (dependencyNames) { const symlinkCache = hostProject.getSymlinkCache(); - for (const name of Array.from(dependencyNames.keys())) { + for (const name of arrayFrom(dependencyNames.keys())) { // Avoid creating a large project that would significantly slow down time to editor interactivity if (dependencySelection === PackageJsonAutoImportPreference.Auto && dependenciesAdded > this.maxDependencies) { hostProject.log(`AutoImportProviderProject: attempted to add more than ${this.maxDependencies} dependencies. Aborting.`); diff --git a/src/server/session.ts b/src/server/session.ts index 0fbf3030b06dd..a2c16033d6ebf 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1,4 +1,5 @@ import { + arrayFrom, arrayReverseIterator, CallHierarchyIncomingCall, CallHierarchyItem, @@ -1338,7 +1339,7 @@ export class Session implements EventSender { private cleanup() { this.cleanProjects("inferred projects", this.projectService.inferredProjects); - this.cleanProjects("configured projects", Array.from(this.projectService.configuredProjects.values())); + this.cleanProjects("configured projects", arrayFrom(this.projectService.configuredProjects.values())); this.cleanProjects("external projects", this.projectService.externalProjects); if (this.host.gc) { this.logger.info(`host.gc()`); @@ -1542,7 +1543,7 @@ export class Session implements EventSender { } } } - definitions = Array.from(definitionSet.values()); + definitions = arrayFrom(definitionSet.values()); } definitions = definitions.filter(d => !d.isAmbient && !d.failedAliasResolution); @@ -1966,7 +1967,7 @@ export class Session implements EventSender { const scriptInfo = Debug.checkDefined(this.projectService.getScriptInfo(fileName)); group.locs.push({ ...toProtocolTextSpanWithContext(textSpan, contextSpan, scriptInfo), ...prefixSuffixText }); } - return Array.from(map.values()); + return arrayFrom(map.values()); } private getReferences(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.ReferencesResponseBody | readonly ReferencedSymbol[] { diff --git a/src/services/codeFixProvider.ts b/src/services/codeFixProvider.ts index 4a8ff6d1bc057..de923d7242433 100644 --- a/src/services/codeFixProvider.ts +++ b/src/services/codeFixProvider.ts @@ -1,4 +1,5 @@ import { + arrayFrom, cast, CodeActionCommand, CodeFixAction, @@ -61,7 +62,7 @@ export function registerCodeFix(reg: CodeFixRegistration) { /** @internal */ export function getSupportedErrorCodes(): readonly string[] { - return Array.from(errorCodeToFixes.keys()); + return arrayFrom(errorCodeToFixes.keys()); } function removeFixIdIfFixAllUnavailable(registration: CodeFixRegistration, diagnostics: Diagnostic[]) { diff --git a/src/services/codefixes/convertToEsModule.ts b/src/services/codefixes/convertToEsModule.ts index 447533c987323..ceff836d7dc8b 100644 --- a/src/services/codefixes/convertToEsModule.ts +++ b/src/services/codefixes/convertToEsModule.ts @@ -5,6 +5,7 @@ import { } from "../_namespaces/ts.codefix"; import { __String, + arrayFrom, ArrowFunction, BinaryExpression, BindingElement, @@ -451,7 +452,7 @@ function convertExportsDotXEquals_replaceNode(name: string | undefined, exported function replaceImportUseSites(node: T, useSitesToUnqualify: Map | undefined): T; function replaceImportUseSites(nodes: NodeArray, useSitesToUnqualify: Map | undefined): NodeArray; function replaceImportUseSites(nodeOrNodes: T | NodeArray, useSitesToUnqualify: Map | undefined) { - if (!useSitesToUnqualify || !some(Array.from(useSitesToUnqualify.keys()), original => rangeContainsRange(nodeOrNodes, original))) { + if (!useSitesToUnqualify || !some(arrayFrom(useSitesToUnqualify.keys()), original => rangeContainsRange(nodeOrNodes, original))) { return nodeOrNodes; } @@ -557,7 +558,7 @@ function convertSingleIdentifierImport(name: Identifier, moduleSpecifier: String } } - const namedBindings = namedBindingsNames.size === 0 ? undefined : Array.from(mapIterator(namedBindingsNames.entries(), ([propertyName, idName]) => + const namedBindings = namedBindingsNames.size === 0 ? undefined : arrayFrom(mapIterator(namedBindingsNames.entries(), ([propertyName, idName]) => factory.createImportSpecifier(/*isTypeOnly*/ false, propertyName === idName ? undefined : factory.createIdentifier(propertyName), factory.createIdentifier(idName)))); if (!namedBindings) { // If it was unused, ensure that we at least import *something*. diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index e344dab4479e0..39d44aede665f 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -1,6 +1,7 @@ import { __String, addToSeen, + arrayFrom, BigIntLiteralType, BinaryExpression, CallExpression, @@ -308,7 +309,7 @@ function getInfo(sourceFile: SourceFile, tokenPos: number, errorCode: number, ch const param = signature.parameters[argIndex].valueDeclaration; if (!(param && isParameter(param) && isIdentifier(param.name))) return undefined; - const properties = Array.from(checker.getUnmatchedProperties(checker.getTypeAtLocation(parent), checker.getParameterType(signature, argIndex), /* requireOptionalProperties */ false, /* matchDiscriminantProperties */ false)); + const properties = arrayFrom(checker.getUnmatchedProperties(checker.getTypeAtLocation(parent), checker.getParameterType(signature, argIndex), /* requireOptionalProperties */ false, /* matchDiscriminantProperties */ false)); if (!length(properties)) return undefined; return { kind: InfoKind.ObjectLiteral, token: param.name, properties, parentDeclaration: parent }; } @@ -316,7 +317,7 @@ function getInfo(sourceFile: SourceFile, tokenPos: number, errorCode: number, ch if (!isMemberName(token)) return undefined; if (isIdentifier(token) && hasInitializer(parent) && parent.initializer && isObjectLiteralExpression(parent.initializer)) { - const properties = Array.from(checker.getUnmatchedProperties(checker.getTypeAtLocation(parent.initializer), checker.getTypeAtLocation(token), /* requireOptionalProperties */ false, /* matchDiscriminantProperties */ false)); + const properties = arrayFrom(checker.getUnmatchedProperties(checker.getTypeAtLocation(parent.initializer), checker.getTypeAtLocation(token), /* requireOptionalProperties */ false, /* matchDiscriminantProperties */ false)); if (!length(properties)) return undefined; return { kind: InfoKind.ObjectLiteral, token, properties, parentDeclaration: parent.initializer }; diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index 674433f0cd51c..493b1aaa6ba31 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -1,6 +1,7 @@ import { AccessorDeclaration, append, + arrayFrom, ArrowFunction, Block, CallExpression, @@ -545,7 +546,7 @@ function createTypeParametersForArguments(checker: TypeChecker, argumentTypePara } } - return Array.from( + return arrayFrom( usedNames.values(), usedName => factory.createTypeParameterDeclaration(/*modifiers*/ undefined, usedName, constraintsByName.get(usedName)?.constraint), ); @@ -650,7 +651,7 @@ export function getArgumentTypesAndTypeParameters(checker: TypeChecker, importAd } } - return { argumentTypeNodes, argumentTypeParameters: Array.from(argumentTypeParameters.entries()) }; + return { argumentTypeNodes, argumentTypeParameters: arrayFrom(argumentTypeParameters.entries()) }; } function isAnonymousObjectConstraintType(type: Type) { diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 51e2bb8db39ae..2d8d7beeaae84 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -2,6 +2,7 @@ import { AnyImportOrRequire, AnyImportOrRequireStatement, AnyImportSyntax, + arrayFrom, CancellationToken, cast, CodeAction, @@ -356,7 +357,7 @@ function createImportAdderWorker(sourceFile: SourceFile, program: Program, useAu sourceFile, importClauseOrBindingPattern, defaultImport, - Array.from(namedImports.entries(), ([name, addAsTypeOnly]) => ({ addAsTypeOnly, name })), + arrayFrom(namedImports.entries(), ([name, addAsTypeOnly]) => ({ addAsTypeOnly, name })), compilerOptions, preferences); }); @@ -369,7 +370,7 @@ function createImportAdderWorker(sourceFile: SourceFile, program: Program, useAu moduleSpecifier, quotePreference, defaultImport, - namedImports && Array.from(namedImports.entries(), ([name, addAsTypeOnly]) => ({ addAsTypeOnly, name })), + namedImports && arrayFrom(namedImports.entries(), ([name, addAsTypeOnly]) => ({ addAsTypeOnly, name })), namespaceLikeImport); newDeclarations = combine(newDeclarations, declarations); }); @@ -1066,7 +1067,7 @@ function getFixesInfoForNonUMDImport({ sourceFile, program, cancellationToken, h const useRequire = shouldUseRequire(sourceFile, program); const exportInfo = getExportInfos(symbolName, isJSXTagName(symbolToken), getMeaningFromLocation(symbolToken), cancellationToken, sourceFile, program, useAutoImportProvider, host, preferences); // TODO(jakebailey): surely this doesn't need the intermediary array - const fixes = Array.from(flatMapIterator(exportInfo.entries(), ([_, exportInfos]) => + const fixes = arrayFrom(flatMapIterator(exportInfo.entries(), ([_, exportInfos]) => getImportFixes(exportInfos, { symbolName, position: symbolToken.getStart(sourceFile) }, isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences).fixes)); return fixes.map(fix => ({ fix, symbolName, errorIdentifierText: symbolToken.text, isJsxNamespaceFix: symbolName !== symbolToken.text })); }); diff --git a/src/services/documentHighlights.ts b/src/services/documentHighlights.ts index 52c7e1e0de1bf..ab021d575aaf7 100644 --- a/src/services/documentHighlights.ts +++ b/src/services/documentHighlights.ts @@ -1,5 +1,6 @@ import { __String, + arrayFrom, arrayToMultiMap, Block, BreakOrContinueStatement, @@ -117,7 +118,7 @@ export namespace DocumentHighlights { if (!referenceEntries) return undefined; const map = arrayToMultiMap(referenceEntries.map(FindAllReferences.toHighlightSpan), e => e.fileName, e => e.span); const getCanonicalFileName = createGetCanonicalFileName(program.useCaseSensitiveFileNames()); - return Array.from(mapDefinedIterator(map.entries(), ([fileName, highlightSpans]) => { + return arrayFrom(mapDefinedIterator(map.entries(), ([fileName, highlightSpans]) => { if (!sourceFilesSet.has(fileName)) { if (!program.redirectTargetsMap.has(toPath(fileName, program.getCurrentDirectory(), getCanonicalFileName))) { return undefined; diff --git a/src/services/documentRegistry.ts b/src/services/documentRegistry.ts index 2c7d5cdda8819..50f660d6bf746 100644 --- a/src/services/documentRegistry.ts +++ b/src/services/documentRegistry.ts @@ -1,4 +1,5 @@ import { + arrayFrom, CompilerOptions, createGetCanonicalFileName, createLanguageServiceSourceFile, @@ -188,7 +189,7 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole const getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames); function reportStats() { - const bucketInfoArray = Array.from(buckets.keys()).filter(name => name && name.charAt(0) === "_").map(name => { + const bucketInfoArray = arrayFrom(buckets.keys()).filter(name => name && name.charAt(0) === "_").map(name => { const entries = buckets.get(name)!; const sourceFiles: { name: string; scriptKind: ScriptKind, refCount: number; }[] = []; entries.forEach((entry, name) => { @@ -383,7 +384,7 @@ export function createDocumentRegistryInternal(useCaseSensitiveFileNames?: boole } function getLanguageServiceRefCounts(path: Path, scriptKind: ScriptKind) { - return Array.from(buckets.entries(), ([key, bucket]): [string, number | undefined] => { + return arrayFrom(buckets.entries(), ([key, bucket]): [string, number | undefined] => { const bucketEntry = bucket.get(path); const entry = bucketEntry && getDocumentRegistryEntry(bucketEntry, scriptKind); return [key, entry && entry.languageServiceRefCount]; diff --git a/src/services/refactorProvider.ts b/src/services/refactorProvider.ts index d452b63eaf7d9..611c846c21c99 100644 --- a/src/services/refactorProvider.ts +++ b/src/services/refactorProvider.ts @@ -1,5 +1,6 @@ import { ApplicableRefactorInfo, + arrayFrom, flatMapIterator, Refactor, RefactorContext, @@ -22,7 +23,7 @@ export function registerRefactor(name: string, refactor: Refactor) { /** @internal */ export function getApplicableRefactors(context: RefactorContext): ApplicableRefactorInfo[] { - return Array.from(flatMapIterator(refactors.values(), refactor => + return arrayFrom(flatMapIterator(refactors.values(), refactor => context.cancellationToken && context.cancellationToken.isCancellationRequested() || !refactor.kinds?.some(kind => refactorKindBeginsWith(kind, context.kind)) ? undefined : refactor.getAvailableActions(context))); diff --git a/src/services/refactors/convertImport.ts b/src/services/refactors/convertImport.ts index 7ced03fd64467..da3a66107def6 100644 --- a/src/services/refactors/convertImport.ts +++ b/src/services/refactors/convertImport.ts @@ -1,5 +1,6 @@ import { ApplicableRefactorInfo, + arrayFrom, codefix, Debug, Diagnostics, @@ -262,7 +263,7 @@ export function doChangeNamedToNamespaceOrDefault(sourceFile: SourceFile, progra ? factory.createIdentifier(namespaceImportName) : factory.createNamespaceImport(factory.createIdentifier(namespaceImportName))); if (neededNamedImports.size) { - const newNamedImports: ImportSpecifier[] = Array.from(neededNamedImports.values(), element => + const newNamedImports: ImportSpecifier[] = arrayFrom(neededNamedImports.values(), element => factory.createImportSpecifier(element.isTypeOnly, element.propertyName && factory.createIdentifier(element.propertyName.text), factory.createIdentifier(element.name.text))); changes.insertNodeAfter(sourceFile, toConvert.parent.parent, updateImport(importDecl, /*defaultImportName*/ undefined, newNamedImports)); } diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index e43be41d6a396..367a685d484f1 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -2,6 +2,7 @@ import { __String, ANONYMOUS, ApplicableRefactorInfo, + arrayFrom, assertType, BindingElement, Block, @@ -1069,7 +1070,7 @@ function extractFunctionInScope( callArguments.push(factory.createIdentifier(name)); }); - const typeParametersAndDeclarations = Array.from(typeParameterUsages.values(), type => ({ type, declaration: getFirstDeclaration(type) })); + const typeParametersAndDeclarations = arrayFrom(typeParameterUsages.values(), type => ({ type, declaration: getFirstDeclaration(type) })); const sortedTypeParametersAndDeclarations = typeParametersAndDeclarations.sort(compareTypesByDeclarationOrder); const typeParameters: readonly TypeParameterDeclaration[] | undefined = sortedTypeParametersAndDeclarations.length === 0 diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index e5d9666fa43ec..6af987675a24b 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -1,6 +1,7 @@ import { addToSeen, altDirectorySeparator, + arrayFrom, CallLikeExpression, CancellationToken, changeExtension, @@ -558,7 +559,7 @@ function getCompletionEntriesForRelativeModules(literalValue: string, scriptDire compilerOptions.rootDirs, literalValue, scriptDirectory, extensionOptions, compilerOptions, host, scriptPath); } else { - return Array.from(getCompletionEntriesForDirectoryFragment(literalValue, scriptDirectory, extensionOptions, host, /*moduleSpecifierIsRelative*/ false, scriptPath).values()); + return arrayFrom(getCompletionEntriesForDirectoryFragment(literalValue, scriptDirectory, extensionOptions, host, /*moduleSpecifierIsRelative*/ false, scriptPath).values()); } } @@ -593,7 +594,7 @@ function getCompletionEntriesForDirectoryFragmentWithRootDirs(rootDirs: string[] const basePath = compilerOptions.project || host.getCurrentDirectory(); const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); const baseDirectories = getBaseDirectoriesFromRootDirs(rootDirs, basePath, scriptDirectory, ignoreCase); - return flatMap(baseDirectories, baseDirectory => Array.from(getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensionOptions, host, /*moduleSpecifierIsRelative*/ true, exclude).values())); + return flatMap(baseDirectories, baseDirectory => arrayFrom(getCompletionEntriesForDirectoryFragment(fragment, baseDirectory, extensionOptions, host, /*moduleSpecifierIsRelative*/ true, exclude).values())); } const enum ReferenceKind { @@ -891,7 +892,7 @@ function getCompletionEntriesForNonRelativeModules( } } - return Array.from(result.values()); + return arrayFrom(result.values()); } function getPatternFromFirstMatchingCondition(target: unknown, conditions: readonly string[]): string | undefined { @@ -1048,7 +1049,7 @@ function getTripleSlashReferenceCompletion(sourceFile: SourceFile, position: num const names = kind === "path" ? getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getExtensionOptions(compilerOptions, ReferenceKind.Filename, sourceFile), host, /*moduleSpecifierIsRelative*/ true, sourceFile.path) : kind === "types" ? getCompletionEntriesFromTypings(host, compilerOptions, scriptPath, getFragmentDirectory(toComplete), getExtensionOptions(compilerOptions, ReferenceKind.ModuleSpecifier, sourceFile)) : Debug.fail(); - return addReplacementSpans(toComplete, range.pos + prefix.length, Array.from(names.values())); + return addReplacementSpans(toComplete, range.pos + prefix.length, arrayFrom(names.values())); } function getCompletionEntriesFromTypings(host: LanguageServiceHost, options: CompilerOptions, scriptPath: string, fragmentDirectory: string | undefined, extensionOptions: ExtensionOptions, result = createNameAndKindSet()): NameAndKindSet { diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index a98e15b1d8360..bda7ba595090c 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -1,5 +1,6 @@ import { addRange, + arrayFrom, BinaryExpression, CallExpression, CheckFlags, @@ -235,7 +236,7 @@ export function getSymbolModifiers(typeChecker: TypeChecker, symbol: Symbol): st if (symbol.flags & SymbolFlags.Optional) { modifiers.add(ScriptElementKindModifier.optionalModifier); } - return modifiers.size > 0 ? Array.from(modifiers.values()).join(",") : ScriptElementKindModifier.none; + return modifiers.size > 0 ? arrayFrom(modifiers.values()).join(",") : ScriptElementKindModifier.none; } /** @internal */ diff --git a/src/testRunner/test262Runner.ts b/src/testRunner/test262Runner.ts index 7393e0bd79b1f..2725fb86f468a 100644 --- a/src/testRunner/test262Runner.ts +++ b/src/testRunner/test262Runner.ts @@ -73,7 +73,7 @@ export class Test262BaselineRunner extends RunnerBase { }); it("has the expected emitted code", () => { - const files = Array.from(testState.compilerResult.js.values()).filter(f => f.file !== Test262BaselineRunner.helpersFilePath); + const files = ts.arrayFrom(testState.compilerResult.js.values()).filter(f => f.file !== Test262BaselineRunner.helpersFilePath); Baseline.runBaseline(testState.filename + ".output.js", Compiler.collateOutputs(files), Test262BaselineRunner.baselineOptions); }); @@ -117,4 +117,4 @@ export class Test262BaselineRunner extends RunnerBase { this.tests.forEach(test => this.runTest(typeof test === "string" ? test : test.file)); } } -} \ No newline at end of file +} diff --git a/src/testRunner/unittests/compilerCore.ts b/src/testRunner/unittests/compilerCore.ts index 45e839e1a5c6a..1b7f82118016f 100644 --- a/src/testRunner/unittests/compilerCore.ts +++ b/src/testRunner/unittests/compilerCore.ts @@ -134,15 +134,15 @@ describe("unittests:: compilerCore", () => { const expected = [0, 1, 2, 3]; let actual: number[]; - actual = Array.from(set.keys()); + actual = ts.arrayFrom(set.keys()); actual.sort(); assert.deepEqual(actual, expected); - actual = Array.from(set.values()); + actual = ts.arrayFrom(set.values()); actual.sort(); assert.deepEqual(actual, expected); - const actualTuple = Array.from(set.entries()); + const actualTuple = ts.arrayFrom(set.entries()); assert.isFalse(actualTuple.some(([v, k]) => v !== k)); actual = actualTuple.map(([v, _]) => v); actual.sort(); diff --git a/src/testRunner/unittests/customTransforms.ts b/src/testRunner/unittests/customTransforms.ts index b20a7f7857aa9..0888c15d0bf34 100644 --- a/src/testRunner/unittests/customTransforms.ts +++ b/src/testRunner/unittests/customTransforms.ts @@ -20,11 +20,11 @@ describe("unittests:: customTransforms", () => { writeFile: (fileName, text) => outputs.set(fileName, text), }; - const program = ts.createProgram(Array.from(fileMap.keys()), { newLine: ts.NewLineKind.LineFeed, ...options }, host); + const program = ts.createProgram(ts.arrayFrom(fileMap.keys()), { newLine: ts.NewLineKind.LineFeed, ...options }, host); program.emit(/*targetSourceFile*/ undefined, host.writeFile, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ false, customTransformers); let content = ""; // TODO(jakebailey): redundant - for (const [file, text] of Array.from(outputs.entries())) { + for (const [file, text] of ts.arrayFrom(outputs.entries())) { if (content) content += "\n\n"; content += `// [${file}]\n`; content += text; diff --git a/src/testRunner/unittests/programApi.ts b/src/testRunner/unittests/programApi.ts index a68b7419f4a76..1ac47d50c2d19 100644 --- a/src/testRunner/unittests/programApi.ts +++ b/src/testRunner/unittests/programApi.ts @@ -12,7 +12,7 @@ function verifyMissingFilePaths(missingPaths: readonly ts.Path[], expected: read assert.isTrue(value, `${missing} to be ${value === undefined ? "not present" : "present only once"}, in actual: ${missingPaths} expected: ${expected}`); map.delete(missing); } - const notFound = Array.from(ts.mapDefinedIterator(map.keys(), k => map.has(k) ? k : undefined)); + const notFound = ts.arrayFrom(ts.mapDefinedIterator(map.keys(), k => map.has(k) ? k : undefined)); assert.equal(notFound.length, 0, `Not found ${notFound} in actual: ${missingPaths} expected: ${expected}`); } diff --git a/src/testRunner/unittests/tsc/helpers.ts b/src/testRunner/unittests/tsc/helpers.ts index eeeb9ee721a2f..7cbc95a005b8f 100644 --- a/src/testRunner/unittests/tsc/helpers.ts +++ b/src/testRunner/unittests/tsc/helpers.ts @@ -235,7 +235,7 @@ function storeDtsSignatures(sys: TscCompileSystem, programs: readonly CommandLin sys, (signature, sourceFiles) => { const exportedModules = ts.BuilderState.getExportedModules(state.exportedModulesMap && sourceFiles[0].exportedModulesFromDeclarationEmit); - dtsSignatureData.set(relativeToBuildInfo(resolvedPath), { signature, exportedModules: exportedModules && Array.from(exportedModules.keys(), relativeToBuildInfo) }); + dtsSignatureData.set(relativeToBuildInfo(resolvedPath), { signature, exportedModules: exportedModules && ts.arrayFrom(exportedModules.keys(), relativeToBuildInfo) }); }, ); }); @@ -705,7 +705,7 @@ function verifyTscEditDiscrepancies({ }); let headerAdded = false; // TODO(jakebailey): redundant? - for (const outputFile of Array.from(sys.writtenFiles.keys())) { + for (const outputFile of ts.arrayFrom(sys.writtenFiles.keys())) { const cleanBuildText = sys.readFile(outputFile); const incrementalBuildText = newSys.readFile(outputFile); if (ts.isBuildInfoFile(outputFile)) { diff --git a/src/testRunner/unittests/tscWatch/incremental.ts b/src/testRunner/unittests/tscWatch/incremental.ts index bd38e5eea6c0d..2773a739e6a80 100644 --- a/src/testRunner/unittests/tscWatch/incremental.ts +++ b/src/testRunner/unittests/tscWatch/incremental.ts @@ -202,8 +202,8 @@ describe("unittests:: tsc-watch:: emit file --incremental", () => { configFilePath: config.path }); - assert.equal(Array.from(state.referencedMap!.keys()).length, 0); - assert.equal(Array.from(state.exportedModulesMap!.keys()).length, 0); + assert.equal(ts.arrayFrom(state.referencedMap!.keys()).length, 0); + assert.equal(ts.arrayFrom(state.exportedModulesMap!.keys()).length, 0); assert.equal(state.semanticDiagnosticsPerFile!.size, 3); assert.deepEqual(state.semanticDiagnosticsPerFile!.get(libFile.path as ts.Path), ts.emptyArray); diff --git a/src/testRunner/unittests/tsserver/helpers.ts b/src/testRunner/unittests/tsserver/helpers.ts index 2804a216b0b90..62ae117c734bd 100644 --- a/src/testRunner/unittests/tsserver/helpers.ts +++ b/src/testRunner/unittests/tsserver/helpers.ts @@ -881,7 +881,7 @@ export function verifyGetErrScenario(scenario: VerifyGetErrScenario) { } export function verifyDynamic(service: ts.server.ProjectService, path: string) { - const info = ts.Debug.checkDefined(service.filenameToScriptInfo.get(path), `Expected ${path} in :: ${JSON.stringify(Array.from(service.filenameToScriptInfo.entries(), ([key, f]) => ({ key, fileName: f.fileName, path: f.path })))}`); + const info = ts.Debug.checkDefined(service.filenameToScriptInfo.get(path), `Expected ${path} in :: ${JSON.stringify(ts.arrayFrom(service.filenameToScriptInfo.entries(), ([key, f]) => ({ key, fileName: f.fileName, path: f.path })))}`); assert.isTrue(info.isDynamic); } From a85d5f67cf80603f83dd731d930ab98682c2763c Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Fri, 6 Jan 2023 11:04:35 -0800 Subject: [PATCH 15/22] Restore loop in builderState --- src/compiler/builderState.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/compiler/builderState.ts b/src/compiler/builderState.ts index aae94e1b4c851..58277c12f9f6e 100644 --- a/src/compiler/builderState.ts +++ b/src/compiler/builderState.ts @@ -521,7 +521,9 @@ export namespace BuilderState { seenMap.add(path); const references = state.referencedMap.getValues(path); if (references) { - queue.push(...references.keys()); + for (const key of references.keys()) { + queue.push(key); + } } } } From 5bf2ee0aab19c09b675cd16b90b8beaebeb12369 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Fri, 6 Jan 2023 11:10:52 -0800 Subject: [PATCH 16/22] Restore zipWith --- src/compiler/core.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 078b5810d947c..dc562324bef93 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -109,10 +109,10 @@ export function reduceLeftIterator(iterator: Iterable | undefined, f: ( /** @internal */ export function zipWith(arrayA: readonly T[], arrayB: readonly U[], callback: (a: T, b: U, index: number) => V): V[] { + const result: V[] = []; Debug.assertEqual(arrayA.length, arrayB.length); - const result: V[] = new Array(arrayA.length); for (let i = 0; i < arrayA.length; i++) { - result[i] = callback(arrayA[i], arrayB[i], i); + result.push(callback(arrayA[i], arrayB[i], i)); } return result; } From fe8663d678a5df4f4b77e28be7e8daae3191320f Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Fri, 6 Jan 2023 11:28:15 -0800 Subject: [PATCH 17/22] Whitespace fixes --- src/compiler/core.ts | 1 + src/server/editorServices.ts | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index dc562324bef93..a238eea89b4bf 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1145,6 +1145,7 @@ export function rangeEquals(array1: readonly T[], array2: readonly T[], pos: } return true; } + /** * Returns the element at a specific offset in an array if non-empty, `undefined` otherwise. * A negative offset indicates the element should be retrieved from the end of the array. diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 8668a1986ee6c..962ba853e612f 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -48,9 +48,7 @@ import { } from "./_namespaces/ts.server"; import { addToSeen, - arrayFrom, - arrayToMap, AssertionLevel, CachedDirectoryStructureHost, From 2f8ea978e604d633d3e7ef2e31175416c2623b6e Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Fri, 6 Jan 2023 11:31:05 -0800 Subject: [PATCH 18/22] Remove emptyIterator --- src/compiler/core.ts | 3 --- src/compiler/resolutionCache.ts | 5 ++--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/compiler/core.ts b/src/compiler/core.ts index a238eea89b4bf..3e19350823c1a 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -580,9 +580,6 @@ export function tryAddToSet(set: Set, value: T) { return false; } -/** @internal */ -export const emptyIterator: IterableIterator = (function*() {})(); // TODO(jakebailey): remove? empty array? - /** @internal */ export function *singleIterator(value: T) { yield value; diff --git a/src/compiler/resolutionCache.ts b/src/compiler/resolutionCache.ts index 1f8d9e179fefb..6784dad515ff7 100644 --- a/src/compiler/resolutionCache.ts +++ b/src/compiler/resolutionCache.ts @@ -17,7 +17,6 @@ import { directorySeparator, DirectoryWatcherCallback, emptyArray, - emptyIterator, endsWith, Extension, extensionIsTS, @@ -1146,8 +1145,8 @@ export function createResolutionCache(resolutionHost: ResolutionCacheHost, rootD function isInvalidatedFailedLookup(locationPath: Path) { return failedLookupChecks?.has(locationPath) || - firstDefinedIterator(startsWithPathChecks?.keys() || emptyIterator, fileOrDirectoryPath => startsWith(locationPath, fileOrDirectoryPath) ? true : undefined) || - firstDefinedIterator(isInDirectoryChecks?.keys() || emptyIterator, fileOrDirectoryPath => isInDirectoryPath(fileOrDirectoryPath, locationPath) ? true : undefined); + firstDefinedIterator(startsWithPathChecks?.keys() || [], fileOrDirectoryPath => startsWith(locationPath, fileOrDirectoryPath) ? true : undefined) || + firstDefinedIterator(isInDirectoryChecks?.keys() || [], fileOrDirectoryPath => isInDirectoryPath(fileOrDirectoryPath, locationPath) ? true : undefined); } function canInvalidatedFailedLookupResolutionWithAffectingLocation(resolution: ResolutionWithFailedLookupLocations) { From beb9a34f997b5b0dacdc4b0b1680746e472eee8a Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Fri, 6 Jan 2023 11:35:07 -0800 Subject: [PATCH 19/22] Fix some todos --- src/harness/vfsUtil.ts | 3 +-- src/testRunner/unittests/customTransforms.ts | 3 +-- src/testRunner/unittests/tsc/helpers.ts | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/harness/vfsUtil.ts b/src/harness/vfsUtil.ts index 9359e93bb4859..d4ae35d37043c 100644 --- a/src/harness/vfsUtil.ts +++ b/src/harness/vfsUtil.ts @@ -1605,8 +1605,7 @@ function* iteratePatchWorker(dirname: string, container: FileSet): IterableItera const entry = normalizeFileSetEntry(container[name]); const file = dirname ? vpath.combine(dirname, name) : name; if (entry instanceof Directory) { - // TODO(jakebailey): redundant? - yield* ts.arrayFrom(iteratePatchWorker(file, entry.files)); + yield* iteratePatchWorker(file, entry.files); } else if (entry instanceof File) { const content = typeof entry.data === "string" ? entry.data : entry.data.toString("utf8"); diff --git a/src/testRunner/unittests/customTransforms.ts b/src/testRunner/unittests/customTransforms.ts index 0888c15d0bf34..a16d2c2a4794b 100644 --- a/src/testRunner/unittests/customTransforms.ts +++ b/src/testRunner/unittests/customTransforms.ts @@ -23,8 +23,7 @@ describe("unittests:: customTransforms", () => { const program = ts.createProgram(ts.arrayFrom(fileMap.keys()), { newLine: ts.NewLineKind.LineFeed, ...options }, host); program.emit(/*targetSourceFile*/ undefined, host.writeFile, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ false, customTransformers); let content = ""; - // TODO(jakebailey): redundant - for (const [file, text] of ts.arrayFrom(outputs.entries())) { + for (const [file, text] of outputs.entries()) { if (content) content += "\n\n"; content += `// [${file}]\n`; content += text; diff --git a/src/testRunner/unittests/tsc/helpers.ts b/src/testRunner/unittests/tsc/helpers.ts index 7cbc95a005b8f..83eda8ebca36a 100644 --- a/src/testRunner/unittests/tsc/helpers.ts +++ b/src/testRunner/unittests/tsc/helpers.ts @@ -704,8 +704,7 @@ function verifyTscEditDiscrepancies({ computeDtsSignatures: true, }); let headerAdded = false; - // TODO(jakebailey): redundant? - for (const outputFile of ts.arrayFrom(sys.writtenFiles.keys())) { + for (const outputFile of sys.writtenFiles.keys()) { const cleanBuildText = sys.readFile(outputFile); const incrementalBuildText = newSys.readFile(outputFile); if (ts.isBuildInfoFile(outputFile)) { From 09f17c630127a88baf3662e9a554a2f1fc7ee947 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Fri, 6 Jan 2023 11:48:41 -0800 Subject: [PATCH 20/22] Fix another TODO --- src/services/codefixes/importFixes.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 2d8d7beeaae84..e6f21c8ca1790 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -1066,10 +1066,11 @@ function getFixesInfoForNonUMDImport({ sourceFile, program, cancellationToken, h const isValidTypeOnlyUseSite = isValidTypeOnlyAliasUseSite(symbolToken); const useRequire = shouldUseRequire(sourceFile, program); const exportInfo = getExportInfos(symbolName, isJSXTagName(symbolToken), getMeaningFromLocation(symbolToken), cancellationToken, sourceFile, program, useAutoImportProvider, host, preferences); - // TODO(jakebailey): surely this doesn't need the intermediary array - const fixes = arrayFrom(flatMapIterator(exportInfo.entries(), ([_, exportInfos]) => - getImportFixes(exportInfos, { symbolName, position: symbolToken.getStart(sourceFile) }, isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences).fixes)); - return fixes.map(fix => ({ fix, symbolName, errorIdentifierText: symbolToken.text, isJsxNamespaceFix: symbolName !== symbolToken.text })); + return arrayFrom( + flatMapIterator(exportInfo.values(), exportInfos => + getImportFixes(exportInfos, { symbolName, position: symbolToken.getStart(sourceFile) }, isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences).fixes), + fix => ({ fix, symbolName, errorIdentifierText: symbolToken.text, isJsxNamespaceFix: symbolName !== symbolToken.text }) + ); }); } From c5458ff20a614bb95edc8266ff3710744b7b1629 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Fri, 6 Jan 2023 13:35:35 -0800 Subject: [PATCH 21/22] Revert "Completely remove Collection/ReadonlyCollection types" This reverts commit 4d68782c965c8d2ffded8e6679d23c11f5d0e6b2. --- src/compiler/builder.ts | 3 ++- src/compiler/corePublic.ts | 21 +++++++++++++++++++++ src/compiler/utilities.ts | 3 ++- src/server/editorServices.ts | 5 +++-- src/services/codefixes/convertToEsModule.ts | 3 ++- src/testRunner/unittests/tsc/helpers.ts | 2 +- 6 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 2bfb44b9e7abb..550baef382984 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -66,6 +66,7 @@ import { Program, ProjectReference, ReadBuildProgramHost, + ReadonlyCollection, returnFalse, returnUndefined, SemanticDiagnosticsBuilderProgram, @@ -276,7 +277,7 @@ export function getPendingEmitKind(optionsOrEmitKind: CompilerOptions | BuilderF return result; } -function hasSameKeys(map1: ReadonlyMap | ReadonlySet | undefined, map2: ReadonlyMap | ReadonlySet | undefined): boolean { +function hasSameKeys(map1: ReadonlyCollection | undefined, map2: ReadonlyCollection | undefined): boolean { // Has same size and every key is present in both maps return map1 === map2 || map1 !== undefined && map2 !== undefined && map1.size === map2.size && !forEachKey(map1, key => !map2.has(key)); } diff --git a/src/compiler/corePublic.ts b/src/compiler/corePublic.ts index 817df8a7587ca..10645e779d6bf 100644 --- a/src/compiler/corePublic.ts +++ b/src/compiler/corePublic.ts @@ -23,6 +23,27 @@ export interface SortedArray extends Array { " __sortedArrayBrand": any; } +/** + * Common read methods for ES6 Map/Set. + * + * @internal + */ +export interface ReadonlyCollection { + readonly size: number; + has(key: K): boolean; + keys(): Iterator; +} + +/** + * Common write methods for ES6 Map/Set. + * + * @internal + */ +export interface Collection extends ReadonlyCollection { + delete(key: K): boolean; + clear(): void; +} + /** * Array that is only intended to be pushed to, never read. * diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index c339ea058ba60..d76ea0241da4c 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -424,6 +424,7 @@ import { PropertySignature, PseudoBigInt, QualifiedName, + ReadonlyCollection, ReadonlyTextRange, removeTrailingDirectorySeparator, RequireOrImportCall, @@ -667,7 +668,7 @@ export function forEachEntry(map: ReadonlyMap, callback: (value: * * @internal */ -export function forEachKey(map: ReadonlyMap | ReadonlySet, callback: (key: K) => T | undefined): T | undefined { +export function forEachKey(map: ReadonlyCollection, callback: (key: K) => T | undefined): T | undefined { const iterator = map.keys(); for (const key of iterator) { const result = callback(key); diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 962ba853e612f..31c3a4c03ad1b 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -143,6 +143,7 @@ import { ProjectPackageJsonInfo, ProjectReference, ReadMapFile, + ReadonlyCollection, removeFileExtension, removeIgnoredPath, removeMinAndVersionNumbers, @@ -3666,7 +3667,7 @@ export class ProjectService { } /** @internal */ - loadAncestorProjectTree(forProjects?: ReadonlyMap | ReadonlySet) { + loadAncestorProjectTree(forProjects?: ReadonlyCollection) { forProjects = forProjects || mapDefinedEntries( this.configuredProjects, (key, project) => !project.isInitialLoadPending() ? [key, true] : undefined @@ -3684,7 +3685,7 @@ export class ProjectService { } } - private ensureProjectChildren(project: ConfiguredProject, forProjects: ReadonlyMap | ReadonlySet, seenProjects: Set) { + private ensureProjectChildren(project: ConfiguredProject, forProjects: ReadonlyCollection, seenProjects: Set) { if (!tryAddToSet(seenProjects, project.canonicalConfigFilePath)) return; // If this project disables child load ignore it diff --git a/src/services/codefixes/convertToEsModule.ts b/src/services/codefixes/convertToEsModule.ts index ceff836d7dc8b..959b9ea4538ad 100644 --- a/src/services/codefixes/convertToEsModule.ts +++ b/src/services/codefixes/convertToEsModule.ts @@ -69,6 +69,7 @@ import { PropertyAccessExpression, QuotePreference, rangeContainsRange, + ReadonlyCollection, ScriptTarget, some, SourceFile, @@ -388,7 +389,7 @@ function convertReExportAll(reExported: StringLiteralLike, checker: TypeChecker) // `module.exports = require("x");` ==> `export * from "x"; export { default } from "x";` const moduleSpecifier = reExported.text; const moduleSymbol = checker.getSymbolAtLocation(reExported); - const exports = moduleSymbol ? moduleSymbol.exports! : emptyMap as ReadonlyMap<__String, never>; + const exports = moduleSymbol ? moduleSymbol.exports! : emptyMap as ReadonlyCollection<__String>; return exports.has(InternalSymbolName.ExportEquals) ? [[reExportDefault(moduleSpecifier)], true] : !exports.has(InternalSymbolName.Default) ? [[reExportStar(moduleSpecifier)], false] : // If there's some non-default export, must include both `export *` and `export default`. diff --git a/src/testRunner/unittests/tsc/helpers.ts b/src/testRunner/unittests/tsc/helpers.ts index 83eda8ebca36a..7e86bf96b40d7 100644 --- a/src/testRunner/unittests/tsc/helpers.ts +++ b/src/testRunner/unittests/tsc/helpers.ts @@ -438,7 +438,7 @@ function addLibAndMakeReadonly(fs: vfs.FileSystem, libContentToAppend?: string) fs.makeReadonly(); } -export function generateSourceMapBaselineFiles(sys: ts.System & { writtenFiles: Map | Set; }) { +export function generateSourceMapBaselineFiles(sys: ts.System & { writtenFiles: ts.ReadonlyCollection; }) { const mapFileNames = ts.mapDefinedIterator(sys.writtenFiles.keys(), f => f.endsWith(".map") ? f : undefined); for (const mapFile of mapFileNames) { const text = Harness.SourceMapRecorder.getSourceMapRecordWithSystem(sys, mapFile); From 3d08b96446a9a11108c9226232a42a5b75e22724 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Fri, 6 Jan 2023 13:41:06 -0800 Subject: [PATCH 22/22] Fix --- src/compiler/corePublic.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/corePublic.ts b/src/compiler/corePublic.ts index 10645e779d6bf..80df5e0515ff7 100644 --- a/src/compiler/corePublic.ts +++ b/src/compiler/corePublic.ts @@ -31,7 +31,7 @@ export interface SortedArray extends Array { export interface ReadonlyCollection { readonly size: number; has(key: K): boolean; - keys(): Iterator; + keys(): IterableIterator; } /**