Skip to content

Commit 672b0e3

Browse files
author
Andy
authored
Have flatMap return a ReadonlyArray by default (#28205)
1 parent c97fc64 commit 672b0e3

File tree

19 files changed

+80
-57
lines changed

19 files changed

+80
-57
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28090,7 +28090,7 @@ namespace ts {
2809028090
return ts.typeHasCallOrConstructSignatures(type, checker);
2809128091
}
2809228092

28093-
function getRootSymbols(symbol: Symbol): Symbol[] {
28093+
function getRootSymbols(symbol: Symbol): ReadonlyArray<Symbol> {
2809428094
const roots = getImmediateRootSymbols(symbol);
2809528095
return roots ? flatMap(roots, getRootSymbols) : [symbol];
2809628096
}

src/compiler/core.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -511,12 +511,27 @@ namespace ts {
511511
* @param array The array to map.
512512
* @param mapfn The callback used to map the result into one or more values.
513513
*/
514-
export function flatMap<T, U>(array: ReadonlyArray<T>, mapfn: (x: T, i: number) => U | ReadonlyArray<U> | undefined): U[];
515-
export function flatMap<T, U>(array: ReadonlyArray<T> | undefined, mapfn: (x: T, i: number) => U | ReadonlyArray<U> | undefined): U[] | undefined;
516-
export function flatMap<T, U>(array: ReadonlyArray<T> | undefined, mapfn: (x: T, i: number) => U | ReadonlyArray<U> | undefined): U[] | undefined {
514+
export function flatMap<T, U>(array: ReadonlyArray<T> | undefined, mapfn: (x: T, i: number) => U | ReadonlyArray<U> | undefined): ReadonlyArray<U> {
517515
let result: U[] | undefined;
518516
if (array) {
519-
result = [];
517+
for (let i = 0; i < array.length; i++) {
518+
const v = mapfn(array[i], i);
519+
if (v) {
520+
if (isArray(v)) {
521+
result = addRange(result, v);
522+
}
523+
else {
524+
result = append(result, v);
525+
}
526+
}
527+
}
528+
}
529+
return result || emptyArray;
530+
}
531+
532+
export function flatMapToMutable<T, U>(array: ReadonlyArray<T> | undefined, mapfn: (x: T, i: number) => U | ReadonlyArray<U> | undefined): U[] {
533+
const result: U[] = [];
534+
if (array) {
520535
for (let i = 0; i < array.length; i++) {
521536
const v = mapfn(array[i], i);
522537
if (v) {

src/compiler/transformers/declarations.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1043,7 +1043,7 @@ namespace ts {
10431043
const modifiers = createNodeArray(ensureModifiers(input, isPrivate));
10441044
const typeParameters = ensureTypeParams(input, input.typeParameters);
10451045
const ctor = getFirstConstructorWithBody(input);
1046-
let parameterProperties: PropertyDeclaration[] | undefined;
1046+
let parameterProperties: ReadonlyArray<PropertyDeclaration> | undefined;
10471047
if (ctor) {
10481048
const oldDiag = getSymbolAccessibilityDiagnostic;
10491049
parameterProperties = compact(flatMap(ctor.parameters, param => {

src/compiler/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2793,7 +2793,7 @@ namespace ts {
27932793
export interface ParseConfigHost {
27942794
useCaseSensitiveFileNames: boolean;
27952795

2796-
readDirectory(rootDir: string, extensions: ReadonlyArray<string>, excludes: ReadonlyArray<string> | undefined, includes: ReadonlyArray<string>, depth?: number): string[];
2796+
readDirectory(rootDir: string, extensions: ReadonlyArray<string>, excludes: ReadonlyArray<string> | undefined, includes: ReadonlyArray<string>, depth?: number): ReadonlyArray<string>;
27972797

27982798
/**
27992799
* Gets a value indicating whether the specified path exists and is a file.
@@ -3079,7 +3079,7 @@ namespace ts {
30793079

30803080
getFullyQualifiedName(symbol: Symbol): string;
30813081
getAugmentedPropertiesOfType(type: Type): Symbol[];
3082-
getRootSymbols(symbol: Symbol): Symbol[];
3082+
getRootSymbols(symbol: Symbol): ReadonlyArray<Symbol>;
30833083
getContextualType(node: Expression): Type | undefined;
30843084
/* @internal */ getContextualTypeForObjectLiteralElement(element: ObjectLiteralElementLike): Type | undefined;
30853085
/* @internal */ getContextualTypeForArgumentAtIndex(call: CallLikeExpression, argIndex: number): Type | undefined;

src/compiler/utilities.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3038,7 +3038,7 @@ namespace ts {
30383038
return fileDiagnostics.get(fileName) || [];
30393039
}
30403040

3041-
const fileDiags: Diagnostic[] = flatMap(filesWithDiagnostics, f => fileDiagnostics.get(f));
3041+
const fileDiags: Diagnostic[] = flatMapToMutable(filesWithDiagnostics, f => fileDiagnostics.get(f));
30423042
if (!nonFileDiagnostics.length) {
30433043
return fileDiags;
30443044
}
@@ -5234,7 +5234,7 @@ namespace ts {
52345234
}
52355235
if (isJSDocTypeAlias(node)) {
52365236
Debug.assert(node.parent.kind === SyntaxKind.JSDocComment);
5237-
return flatMap(node.parent.tags, tag => isJSDocTemplateTag(tag) ? tag.typeParameters : undefined) as ReadonlyArray<TypeParameterDeclaration>;
5237+
return flatMap(node.parent.tags, tag => isJSDocTemplateTag(tag) ? tag.typeParameters : undefined);
52385238
}
52395239
if (node.typeParameters) {
52405240
return node.typeParameters;
@@ -7777,7 +7777,7 @@ namespace ts {
77777777
return `^(${pattern})${terminator}`;
77787778
}
77797779

7780-
export function getRegularExpressionsForWildcards(specs: ReadonlyArray<string> | undefined, basePath: string, usage: "files" | "directories" | "exclude"): string[] | undefined {
7780+
export function getRegularExpressionsForWildcards(specs: ReadonlyArray<string> | undefined, basePath: string, usage: "files" | "directories" | "exclude"): ReadonlyArray<string> | undefined {
77817781
if (specs === undefined || specs.length === 0) {
77827782
return undefined;
77837783
}

src/harness/fourslash.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ namespace FourSlash {
491491
];
492492
}
493493

494-
private getAllDiagnostics(): ts.Diagnostic[] {
494+
private getAllDiagnostics(): ReadonlyArray<ts.Diagnostic> {
495495
return ts.flatMap(this.languageServiceAdapterHost.getFilenames(), fileName => {
496496
if (!ts.isAnySupportedFileExtension(fileName)) {
497497
return [];
@@ -532,7 +532,7 @@ namespace FourSlash {
532532
predicate(start!, start! + length!, startMarker.position, endMarker === undefined ? undefined : endMarker.position)); // TODO: GH#18217
533533
}
534534

535-
private printErrorLog(expectErrors: boolean, errors: ts.Diagnostic[]) {
535+
private printErrorLog(expectErrors: boolean, errors: ReadonlyArray<ts.Diagnostic>): void {
536536
if (expectErrors) {
537537
Harness.IO.log("Expected error not found. Error list is:");
538538
}
@@ -613,7 +613,7 @@ namespace FourSlash {
613613
this.verifyGoToX(arg0, endMarkerNames, () => this.getGoToDefinitionAndBoundSpan());
614614
}
615615

616-
private getGoToDefinition(): ts.DefinitionInfo[] {
616+
private getGoToDefinition(): ReadonlyArray<ts.DefinitionInfo> {
617617
return this.languageService.getDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition)!;
618618
}
619619

@@ -626,7 +626,7 @@ namespace FourSlash {
626626
this.languageService.getTypeDefinitionAtPosition(this.activeFile.fileName, this.currentCaretPosition));
627627
}
628628

629-
private verifyGoToX(arg0: any, endMarkerNames: ArrayOrSingle<string> | undefined, getDefs: () => ts.DefinitionInfo[] | ts.DefinitionInfoAndBoundSpan | undefined) {
629+
private verifyGoToX(arg0: any, endMarkerNames: ArrayOrSingle<string> | undefined, getDefs: () => ReadonlyArray<ts.DefinitionInfo> | ts.DefinitionInfoAndBoundSpan | undefined) {
630630
if (endMarkerNames) {
631631
this.verifyGoToXPlain(arg0, endMarkerNames, getDefs);
632632
}
@@ -646,7 +646,7 @@ namespace FourSlash {
646646
}
647647
}
648648

649-
private verifyGoToXPlain(startMarkerNames: ArrayOrSingle<string>, endMarkerNames: ArrayOrSingle<string>, getDefs: () => ts.DefinitionInfo[] | ts.DefinitionInfoAndBoundSpan | undefined) {
649+
private verifyGoToXPlain(startMarkerNames: ArrayOrSingle<string>, endMarkerNames: ArrayOrSingle<string>, getDefs: () => ReadonlyArray<ts.DefinitionInfo> | ts.DefinitionInfoAndBoundSpan | undefined) {
650650
for (const start of toArray(startMarkerNames)) {
651651
this.verifyGoToXSingle(start, endMarkerNames, getDefs);
652652
}
@@ -1890,7 +1890,7 @@ Actual: ${stringify(fullActual)}`);
18901890

18911891
public verifyRangesInImplementationList(markerName: string) {
18921892
this.goToMarker(markerName);
1893-
const implementations: ImplementationLocationInformation[] = this.languageService.getImplementationAtPosition(this.activeFile.fileName, this.currentCaretPosition)!;
1893+
const implementations: ReadonlyArray<ImplementationLocationInformation> = this.languageService.getImplementationAtPosition(this.activeFile.fileName, this.currentCaretPosition)!;
18941894
if (!implementations || !implementations.length) {
18951895
this.raiseError("verifyRangesInImplementationList failed - expected to find at least one implementation location but got 0");
18961896
}
@@ -2383,7 +2383,7 @@ Actual: ${stringify(fullActual)}`);
23832383
* Rerieves a codefix satisfying the parameters, or undefined if no such codefix is found.
23842384
* @param fileName Path to file where error should be retrieved from.
23852385
*/
2386-
private getCodeFixes(fileName: string, errorCode?: number, preferences: ts.UserPreferences = ts.emptyOptions): ts.CodeFixAction[] {
2386+
private getCodeFixes(fileName: string, errorCode?: number, preferences: ts.UserPreferences = ts.emptyOptions): ReadonlyArray<ts.CodeFixAction> {
23872387
const diagnosticsForCodeFix = this.getDiagnostics(fileName, /*includeSuggestions*/ true).map(diagnostic => ({
23882388
start: diagnostic.start,
23892389
length: diagnostic.length,

src/harness/harness.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ namespace Harness {
490490
getExecutingFilePath(): string;
491491
getWorkspaceRoot(): string;
492492
exit(exitCode?: number): void;
493-
readDirectory(path: string, extension?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): string[];
493+
readDirectory(path: string, extension?: ReadonlyArray<string>, exclude?: ReadonlyArray<string>, include?: ReadonlyArray<string>, depth?: number): ReadonlyArray<string>;
494494
getAccessibleFileSystemEntries(dirname: string): ts.FileSystemEntries;
495495
tryEnableSourceMapsForHost?(): void;
496496
getEnvironmentVariable?(name: string): string;

src/server/project.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ namespace ts.server {
548548
}
549549

550550
getExternalFiles(): SortedReadonlyArray<string> {
551-
return toSortedArray(flatMap(this.plugins, plugin => {
551+
return toSortedArray(flatMapToMutable(this.plugins, plugin => {
552552
if (typeof plugin.getExternalFiles !== "function") return;
553553
try {
554554
return plugin.getExternalFiles(this);

src/server/protocol.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,7 @@ namespace ts.server.protocol {
10231023
/**
10241024
* The file locations referencing the symbol.
10251025
*/
1026-
refs: ReferencesResponseItem[];
1026+
refs: ReadonlyArray<ReferencesResponseItem>;
10271027

10281028
/**
10291029
* The name of the symbol.

src/server/session.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ namespace ts.server {
267267
projects: Projects,
268268
action: (project: Project, value: T) => ReadonlyArray<U> | U | undefined,
269269
): U[] {
270-
const outputs = flatMap(isArray(projects) ? projects : projects.projects, project => action(project, defaultValue));
270+
const outputs = flatMapToMutable(isArray(projects) ? projects : projects.projects, project => action(project, defaultValue));
271271
if (!isArray(projects) && projects.symLinkedProjects) {
272272
projects.symLinkedProjects.forEach((projects, path) => {
273273
const value = getValue(path as Path);
@@ -1230,7 +1230,7 @@ namespace ts.server {
12301230
const nameSpan = nameInfo && nameInfo.textSpan;
12311231
const symbolStartOffset = nameSpan ? scriptInfo.positionToLineOffset(nameSpan.start).offset : 0;
12321232
const symbolName = nameSpan ? scriptInfo.getSnapshot().getText(nameSpan.start, textSpanEnd(nameSpan)) : "";
1233-
const refs: protocol.ReferencesResponseItem[] = flatMap(references, referencedSymbol =>
1233+
const refs: ReadonlyArray<protocol.ReferencesResponseItem> = flatMap(references, referencedSymbol =>
12341234
referencedSymbol.references.map(({ fileName, textSpan, isWriteAccess, isDefinition }): protocol.ReferencesResponseItem => {
12351235
const scriptInfo = Debug.assertDefined(this.projectService.getScriptInfo(fileName));
12361236
const start = scriptInfo.positionToLineOffset(textSpan.start);

0 commit comments

Comments
 (0)