mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Use more explicit operations in core helpers (and other nits) (#58873)
This commit is contained in:
1 parent
4239025fa3
commit
4935e14901
9 files changed
+102
-123
No files matched your search
@@ -17,10 +17,10 @@ import {
|
||||
appendIfUnique,
|
||||
ArrayBindingPattern,
|
||||
arrayFrom,
|
||||
arrayIsEqualTo,
|
||||
arrayIsHomogeneous,
|
||||
ArrayLiteralExpression,
|
||||
arrayOf,
|
||||
arraysEqual,
|
||||
arrayToMultiMap,
|
||||
ArrayTypeNode,
|
||||
ArrowFunction,
|
||||
@@ -25861,7 +25861,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
function inferTypesFromTemplateLiteralType(source: Type, target: TemplateLiteralType): Type[] | undefined {
|
||||
return source.flags & TypeFlags.StringLiteral ? inferFromLiteralPartsToTemplateLiteral([(source as StringLiteralType).value], emptyArray, target) :
|
||||
source.flags & TypeFlags.TemplateLiteral ?
|
||||
arraysEqual((source as TemplateLiteralType).texts, target.texts) ? map((source as TemplateLiteralType).types, (s, i) => {
|
||||
arrayIsEqualTo((source as TemplateLiteralType).texts, target.texts) ? map((source as TemplateLiteralType).types, (s, i) => {
|
||||
return isTypeAssignableTo(getBaseConstraintOrType(s), getBaseConstraintOrType(target.types[i])) ? s : getStringLikeTypeForType(s);
|
||||
}) :
|
||||
inferFromLiteralPartsToTemplateLiteral((source as TemplateLiteralType).texts, (source as TemplateLiteralType).types, target) :
|
||||
@@ -28628,7 +28628,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return getEvolvingArrayType(getUnionType(map(types, getElementTypeOfEvolvingArrayType)));
|
||||
}
|
||||
const result = recombineUnknownType(getUnionType(sameMap(types, finalizeEvolvingArrayType), subtypeReduction));
|
||||
if (result !== declaredType && result.flags & declaredType.flags & TypeFlags.Union && arraysEqual((result as UnionType).types, (declaredType as UnionType).types)) {
|
||||
if (result !== declaredType && result.flags & declaredType.flags & TypeFlags.Union && arrayIsEqualTo((result as UnionType).types, (declaredType as UnionType).types)) {
|
||||
return declaredType;
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -2576,9 +2576,7 @@ export function convertToTSConfig(configParseResult: ParsedCommandLine, configFi
|
||||
|
||||
/** @internal */
|
||||
export function optionMapToObject(optionMap: Map<string, CompilerOptionsValue>): object {
|
||||
return {
|
||||
...arrayFrom(optionMap.entries()).reduce((prev, cur) => ({ ...prev, [cur[0]]: cur[1] }), {}),
|
||||
};
|
||||
return Object.fromEntries(optionMap);
|
||||
}
|
||||
|
||||
function filterSameAsDefaultInclude(specs: readonly string[] | undefined) {
|
||||
|
||||
+79
-95
@@ -11,6 +11,8 @@ import {
|
||||
TextSpan,
|
||||
} from "./_namespaces/ts.js";
|
||||
|
||||
/* eslint-disable @typescript-eslint/prefer-for-of */
|
||||
|
||||
/** @internal */
|
||||
export const emptyArray: never[] = [] as never[];
|
||||
/** @internal */
|
||||
@@ -20,7 +22,7 @@ export const emptySet: ReadonlySet<never> = new Set<never>();
|
||||
|
||||
/** @internal */
|
||||
export function length(array: readonly any[] | undefined): number {
|
||||
return array ? array.length : 0;
|
||||
return array !== undefined ? array.length : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -31,7 +33,7 @@ export function length(array: readonly any[] | undefined): number {
|
||||
* @internal
|
||||
*/
|
||||
export function forEach<T, U>(array: readonly T[] | undefined, callback: (element: T, index: number) => U | undefined): U | undefined {
|
||||
if (array) {
|
||||
if (array !== undefined) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const result = callback(array[i], i);
|
||||
if (result) {
|
||||
@@ -48,7 +50,7 @@ export function forEach<T, U>(array: readonly T[] | undefined, callback: (elemen
|
||||
* @internal
|
||||
*/
|
||||
export function forEachRight<T, U>(array: readonly T[] | undefined, callback: (element: T, index: number) => U | undefined): U | undefined {
|
||||
if (array) {
|
||||
if (array !== undefined) {
|
||||
for (let i = array.length - 1; i >= 0; i--) {
|
||||
const result = callback(array[i], i);
|
||||
if (result) {
|
||||
@@ -124,7 +126,7 @@ export function intersperse<T>(input: T[], element: T): T[] {
|
||||
}
|
||||
const result: T[] = [];
|
||||
for (let i = 0, n = input.length; i < n; i++) {
|
||||
if (i) result.push(element);
|
||||
if (i !== 0) result.push(element);
|
||||
result.push(input[i]);
|
||||
}
|
||||
return result;
|
||||
@@ -143,7 +145,7 @@ export function every<T, U extends T>(array: readonly T[] | undefined, callback:
|
||||
/** @internal */
|
||||
export function every<T>(array: readonly T[] | undefined, callback: (element: T, index: number) => boolean): boolean;
|
||||
export function every<T>(array: readonly T[] | undefined, callback: (element: T, index: number) => boolean): boolean {
|
||||
if (array) {
|
||||
if (array !== undefined) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
if (!callback(array[i], i)) {
|
||||
return false;
|
||||
@@ -234,9 +236,9 @@ export function findMap<T, U>(array: readonly T[], callback: (element: T, index:
|
||||
|
||||
/** @internal */
|
||||
export function contains<T>(array: readonly T[] | undefined, value: T, equalityComparer: EqualityComparer<T> = equateValues): boolean {
|
||||
if (array) {
|
||||
for (const v of array) {
|
||||
if (equalityComparer(v, value)) {
|
||||
if (array !== undefined) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
if (equalityComparer(array[i], value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -244,14 +246,9 @@ export function contains<T>(array: readonly T[] | undefined, value: T, equalityC
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function arraysEqual<T>(a: readonly T[], b: readonly T[], equalityComparer: EqualityComparer<T> = equateValues): boolean {
|
||||
return a.length === b.length && a.every((x, i) => equalityComparer(x, b[i]));
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function indexOfAnyCharCode(text: string, charCodes: readonly number[], start?: number): number {
|
||||
for (let i = start || 0; i < text.length; i++) {
|
||||
for (let i = start ?? 0; i < text.length; i++) {
|
||||
if (contains(charCodes, text.charCodeAt(i))) {
|
||||
return i;
|
||||
}
|
||||
@@ -262,7 +259,7 @@ export function indexOfAnyCharCode(text: string, charCodes: readonly number[], s
|
||||
/** @internal */
|
||||
export function countWhere<T>(array: readonly T[] | undefined, predicate: (x: T, i: number) => boolean): number {
|
||||
let count = 0;
|
||||
if (array) {
|
||||
if (array !== undefined) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const v = array[i];
|
||||
if (predicate(v, i)) {
|
||||
@@ -296,7 +293,7 @@ export function filter<T, U extends T>(array: readonly T[] | undefined, f: (x: T
|
||||
export function filter<T>(array: readonly T[] | undefined, f: (x: T) => boolean): readonly T[] | undefined;
|
||||
/** @internal */
|
||||
export function filter<T>(array: readonly T[] | undefined, f: (x: T) => boolean): readonly T[] | undefined {
|
||||
if (array) {
|
||||
if (array !== undefined) {
|
||||
const len = array.length;
|
||||
let i = 0;
|
||||
while (i < len && f(array[i])) i++;
|
||||
@@ -340,7 +337,7 @@ export function map<T, U>(array: readonly T[] | undefined, f: (x: T, i: number)
|
||||
/** @internal */
|
||||
export function map<T, U>(array: readonly T[] | undefined, f: (x: T, i: number) => U): U[] | undefined {
|
||||
let result: U[] | undefined;
|
||||
if (array) {
|
||||
if (array !== undefined) {
|
||||
result = [];
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
result.push(f(array[i], i));
|
||||
@@ -369,7 +366,7 @@ export function sameMap<T, U = T>(array: T[] | undefined, f: (x: T, i: number) =
|
||||
export function sameMap<T, U = T>(array: readonly T[] | undefined, f: (x: T, i: number) => U): readonly U[] | undefined;
|
||||
/** @internal */
|
||||
export function sameMap<T, U = T>(array: readonly T[] | undefined, f: (x: T, i: number) => U): readonly U[] | undefined {
|
||||
if (array) {
|
||||
if (array !== undefined) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const item = array[i];
|
||||
const mapped = f(item, i);
|
||||
@@ -395,7 +392,8 @@ export function sameMap<T, U = T>(array: readonly T[] | undefined, f: (x: T, i:
|
||||
*/
|
||||
export function flatten<T>(array: T[][] | readonly (T | readonly T[] | undefined)[]): T[] {
|
||||
const result = [];
|
||||
for (const v of array) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const v = array[i];
|
||||
if (v) {
|
||||
if (isArray(v)) {
|
||||
addRange(result, v);
|
||||
@@ -418,7 +416,7 @@ export function flatten<T>(array: T[][] | readonly (T | readonly T[] | undefined
|
||||
*/
|
||||
export function flatMap<T, U>(array: readonly T[] | undefined, mapfn: (x: T, i: number) => U | readonly U[] | undefined): readonly U[] {
|
||||
let result: U[] | undefined;
|
||||
if (array) {
|
||||
if (array !== undefined) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const v = mapfn(array[i], i);
|
||||
if (v) {
|
||||
@@ -431,13 +429,13 @@ export function flatMap<T, U>(array: readonly T[] | undefined, mapfn: (x: T, i:
|
||||
}
|
||||
}
|
||||
}
|
||||
return result || emptyArray;
|
||||
return result ?? emptyArray;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function flatMapToMutable<T, U>(array: readonly T[] | undefined, mapfn: (x: T, i: number) => U | readonly U[] | undefined): U[] {
|
||||
const result: U[] = [];
|
||||
if (array) {
|
||||
if (array !== undefined) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const v = mapfn(array[i], i);
|
||||
if (v) {
|
||||
@@ -477,7 +475,7 @@ export function sameFlatMap<T>(array: readonly T[], mapfn: (x: T, i: number) =>
|
||||
/** @internal */
|
||||
export function sameFlatMap<T>(array: readonly T[], mapfn: (x: T, i: number) => T | readonly T[]): readonly T[] {
|
||||
let result: T[] | undefined;
|
||||
if (array) {
|
||||
if (array !== undefined) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const item = array[i];
|
||||
const mapped = mapfn(item, i);
|
||||
@@ -494,7 +492,7 @@ export function sameFlatMap<T>(array: readonly T[], mapfn: (x: T, i: number) =>
|
||||
}
|
||||
}
|
||||
}
|
||||
return result || array;
|
||||
return result ?? array;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -513,7 +511,7 @@ export function mapAllOrFail<T, U>(array: readonly T[], mapFn: (x: T, i: number)
|
||||
/** @internal */
|
||||
export function mapDefined<T, U>(array: readonly T[] | undefined, mapFn: (x: T, i: number) => U | undefined): U[] {
|
||||
const result: U[] = [];
|
||||
if (array) {
|
||||
if (array !== undefined) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const mapped = mapFn(array[i], i);
|
||||
if (mapped !== undefined) {
|
||||
@@ -534,30 +532,6 @@ export function* mapDefinedIterator<T, U>(iter: Iterable<T>, mapFn: (x: T) => U
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function mapDefinedEntries<K1, V1, K2, V2>(map: ReadonlyMap<K1, V1>, f: (key: K1, value: V1) => readonly [K2, V2] | undefined): Map<K2, V2>;
|
||||
/** @internal */
|
||||
export function mapDefinedEntries<K1, V1, K2, V2>(map: ReadonlyMap<K1, V1> | undefined, f: (key: K1, value: V1) => readonly [K2 | undefined, V2 | undefined] | undefined): Map<K2, V2> | undefined;
|
||||
/** @internal */
|
||||
export function mapDefinedEntries<K1, V1, K2, V2>(map: ReadonlyMap<K1, V1> | undefined, f: (key: K1, value: V1) => readonly [K2 | undefined, V2 | undefined] | undefined): Map<K2, V2> | undefined {
|
||||
if (!map) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const result = new Map<K2, V2>();
|
||||
map.forEach((value, key) => {
|
||||
const entry = f(key, value);
|
||||
if (entry !== undefined) {
|
||||
const [newKey, newValue] = entry;
|
||||
if (newKey !== undefined && newValue !== undefined) {
|
||||
result.set(newKey, newValue);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getOrUpdate<K, V>(map: Map<K, V>, key: K, callback: () => V) {
|
||||
if (map.has(key)) {
|
||||
@@ -597,7 +571,7 @@ export function spanMap<T, K, U>(array: readonly T[] | undefined, keyfn: (x: T,
|
||||
/** @internal */
|
||||
export function spanMap<T, K, U>(array: readonly T[] | undefined, keyfn: (x: T, i: number) => K, mapfn: (chunk: T[], key: K, start: number, end: number) => U): U[] | undefined {
|
||||
let result: U[] | undefined;
|
||||
if (array) {
|
||||
if (array !== undefined) {
|
||||
result = [];
|
||||
const len = array.length;
|
||||
let previousKey: K | undefined;
|
||||
@@ -641,7 +615,7 @@ export function mapEntries<K1, V1, K2, V2>(map: ReadonlyMap<K1, V1>, f: (key: K1
|
||||
export function mapEntries<K1, V1, K2, V2>(map: ReadonlyMap<K1, V1> | undefined, f: (key: K1, value: V1) => readonly [K2, V2]): Map<K2, V2> | undefined;
|
||||
/** @internal */
|
||||
export function mapEntries<K1, V1, K2, V2>(map: ReadonlyMap<K1, V1> | undefined, f: (key: K1, value: V1) => readonly [K2, V2]): Map<K2, V2> | undefined {
|
||||
if (!map) {
|
||||
if (map === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -659,10 +633,10 @@ export function some<T>(array: readonly T[] | undefined): array is readonly T[];
|
||||
export function some<T>(array: readonly T[] | undefined, predicate: (value: T) => boolean): boolean;
|
||||
/** @internal */
|
||||
export function some<T>(array: readonly T[] | undefined, predicate?: (value: T) => boolean): boolean {
|
||||
if (array) {
|
||||
if (predicate) {
|
||||
for (const v of array) {
|
||||
if (predicate(v)) {
|
||||
if (array !== undefined) {
|
||||
if (predicate !== undefined) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
if (predicate(array[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -713,8 +687,8 @@ export function concatenate<T>(array1: T[] | undefined, array2: T[] | undefined)
|
||||
export function concatenate<T>(array1: readonly T[] | undefined, array2: readonly T[] | undefined): readonly T[] | undefined;
|
||||
/** @internal */
|
||||
export function concatenate<T>(array1: readonly T[] | undefined, array2: readonly T[] | undefined): readonly T[] | undefined {
|
||||
if (!some(array2)) return array1;
|
||||
if (!some(array1)) return array2;
|
||||
if (array2 === undefined || array2.length === 0) return array1;
|
||||
if (array1 === undefined || array1.length === 0) return array2;
|
||||
return [...array1, ...array2];
|
||||
}
|
||||
|
||||
@@ -751,8 +725,8 @@ function deduplicateRelational<T>(array: readonly T[], equalityComparer: Equalit
|
||||
|
||||
function deduplicateEquality<T>(array: readonly T[], equalityComparer: EqualityComparer<T>) {
|
||||
const result: T[] = [];
|
||||
for (const item of array) {
|
||||
pushIfUnique(result, item, equalityComparer);
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
pushIfUnique(result, array[i], equalityComparer);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -850,7 +824,7 @@ export function sortAndDeduplicate(array: readonly string[]): SortedReadonlyArra
|
||||
export function sortAndDeduplicate<T>(array: readonly T[], comparer: Comparer<T>, equalityComparer?: EqualityComparer<T>): SortedReadonlyArray<T>;
|
||||
/** @internal */
|
||||
export function sortAndDeduplicate<T>(array: readonly T[], comparer?: Comparer<T>, equalityComparer?: EqualityComparer<T>): SortedReadonlyArray<T> {
|
||||
return deduplicateSorted(sort(array, comparer), equalityComparer || comparer || compareStringsCaseSensitive as any as Comparer<T>);
|
||||
return deduplicateSorted(sort(array, comparer), equalityComparer ?? comparer ?? compareStringsCaseSensitive as any as Comparer<T>);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -866,7 +840,7 @@ export function arrayIsSorted<T>(array: readonly T[], comparer: Comparer<T>) {
|
||||
|
||||
/** @internal */
|
||||
export function arrayIsEqualTo<T>(array1: readonly T[] | undefined, array2: readonly T[] | undefined, equalityComparer: (a: T, b: T, index: number) => boolean = equateValues): boolean {
|
||||
if (!array1 || !array2) {
|
||||
if (array1 === undefined || array2 === undefined) {
|
||||
return array1 === array2;
|
||||
}
|
||||
|
||||
@@ -899,20 +873,20 @@ export function compact<T>(array: readonly T[]): readonly T[]; // eslint-disable
|
||||
/** @internal */
|
||||
export function compact<T>(array: readonly T[]): readonly T[] {
|
||||
let result: T[] | undefined;
|
||||
if (array) {
|
||||
if (array !== undefined) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const v = array[i];
|
||||
if (result || !v) {
|
||||
if (!result) {
|
||||
result = array.slice(0, i);
|
||||
}
|
||||
// Either the result has been initialized (and is looking to collect truthy values separately),
|
||||
// or we've hit our first falsy value and need to copy over the current stretch of truthy values.
|
||||
if (result ?? !v) {
|
||||
result ??= array.slice(0, i);
|
||||
if (v) {
|
||||
result.push(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result || array;
|
||||
return result ?? array;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1075,7 +1049,7 @@ export function pushIfUnique<T>(array: T[], toAdd: T, equalityComparer?: Equalit
|
||||
* @internal
|
||||
*/
|
||||
export function appendIfUnique<T>(array: T[] | undefined, toAdd: T, equalityComparer?: EqualityComparer<T>): T[] {
|
||||
if (array) {
|
||||
if (array !== undefined) {
|
||||
pushIfUnique(array, toAdd, equalityComparer);
|
||||
return array;
|
||||
}
|
||||
@@ -1136,7 +1110,7 @@ export function rangeEquals<T>(array1: readonly T[], array2: readonly T[], pos:
|
||||
export const elementAt: <T>(array: readonly T[] | undefined, offset: number) => T | undefined = !!Array.prototype.at
|
||||
? (array, offset) => array?.at(offset)
|
||||
: (array, offset) => {
|
||||
if (array) {
|
||||
if (array !== undefined) {
|
||||
offset = toOffset(array, offset);
|
||||
if (offset < array.length) {
|
||||
return array[offset];
|
||||
@@ -1156,7 +1130,7 @@ export function firstOrUndefined<T>(array: readonly T[] | undefined): T | undefi
|
||||
|
||||
/** @internal */
|
||||
export function firstOrUndefinedIterator<T>(iter: Iterable<T> | undefined): T | undefined {
|
||||
if (iter) {
|
||||
if (iter !== undefined) {
|
||||
for (const value of iter) {
|
||||
return value;
|
||||
}
|
||||
@@ -1199,7 +1173,7 @@ export function last<T>(array: readonly T[]): T {
|
||||
* @internal
|
||||
*/
|
||||
export function singleOrUndefined<T>(array: readonly T[] | undefined): T | undefined {
|
||||
return array && array.length === 1
|
||||
return array !== undefined && array.length === 1
|
||||
? array[0]
|
||||
: undefined;
|
||||
}
|
||||
@@ -1228,7 +1202,7 @@ export function singleOrMany<T>(array: T[] | undefined): T | T[] | undefined;
|
||||
export function singleOrMany<T>(array: readonly T[] | undefined): T | readonly T[] | undefined;
|
||||
/** @internal */
|
||||
export function singleOrMany<T>(array: readonly T[] | undefined): T | readonly T[] | undefined {
|
||||
return array && array.length === 1
|
||||
return array !== undefined && array.length === 1
|
||||
? array[0]
|
||||
: array;
|
||||
}
|
||||
@@ -1274,7 +1248,7 @@ export function binarySearchKey<T, U>(array: readonly T[], key: U, keySelector:
|
||||
return -1;
|
||||
}
|
||||
|
||||
let low = offset || 0;
|
||||
let low = offset ?? 0;
|
||||
let high = array.length - 1;
|
||||
while (low <= high) {
|
||||
const middle = low + ((high - low) >> 1);
|
||||
@@ -1478,7 +1452,8 @@ export function arrayToMap<T, U>(array: readonly T[], makeKey: (value: T) => str
|
||||
/** @internal */
|
||||
export function arrayToMap<K, V1, V2>(array: readonly V1[], makeKey: (value: V1) => K | undefined, makeValue: (value: V1) => V1 | V2 = identity): Map<K, V1 | V2> {
|
||||
const result = new Map<K, V1 | V2>();
|
||||
for (const value of array) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const value = array[i];
|
||||
const key = makeKey(value);
|
||||
if (key !== undefined) result.set(key, makeValue(value));
|
||||
}
|
||||
@@ -1492,7 +1467,8 @@ export function arrayToNumericMap<T, U>(array: readonly T[], makeKey: (value: T)
|
||||
/** @internal */
|
||||
export function arrayToNumericMap<T, U>(array: readonly T[], makeKey: (value: T) => number, makeValue: (value: T) => T | U = identity): (T | U)[] {
|
||||
const result: (T | U)[] = [];
|
||||
for (const value of array) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
const value = array[i];
|
||||
result[makeKey(value)] = makeValue(value);
|
||||
}
|
||||
return result;
|
||||
@@ -1505,7 +1481,8 @@ export function arrayToMultiMap<K, V, U>(values: readonly V[], makeKey: (value:
|
||||
/** @internal */
|
||||
export function arrayToMultiMap<K, V, U>(values: readonly V[], makeKey: (value: V) => K, makeValue: (value: V) => V | U = identity): MultiMap<K, V | U> {
|
||||
const result = createMultiMap<K, V | U>();
|
||||
for (const value of values) {
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
const value = values[i];
|
||||
result.add(makeKey(value), makeValue(value));
|
||||
}
|
||||
return result;
|
||||
@@ -1530,8 +1507,9 @@ export function groupBy<T, U extends T>(values: readonly T[] | undefined, keySel
|
||||
export function groupBy<T, K extends string | number | boolean | null | undefined>(values: readonly T[] | undefined, keySelector: (value: T) => K): { [P in K as `${P}`]?: T[]; }; // eslint-disable-line no-restricted-syntax
|
||||
export function groupBy<T, K extends string | number | boolean | null | undefined>(values: readonly T[] | undefined, keySelector: (value: T) => K): { [P in K as `${P}`]?: T[]; } { // eslint-disable-line no-restricted-syntax
|
||||
const result: Record<string, T[]> = {};
|
||||
if (values) {
|
||||
for (const value of values) {
|
||||
if (values !== undefined) {
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
const value = values[i];
|
||||
const key = `${keySelector(value)}`;
|
||||
const array = result[key] ??= [];
|
||||
array.push(value);
|
||||
@@ -1586,7 +1564,7 @@ export function copyProperties<T1 extends T2, T2>(first: T1, second: T2) {
|
||||
|
||||
/** @internal */
|
||||
export function maybeBind<T, A extends any[], R>(obj: T, fn: ((this: T, ...args: A) => R) | undefined): ((...args: A) => R) | undefined {
|
||||
return fn ? fn.bind(obj) : undefined;
|
||||
return fn?.bind(obj);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -1613,7 +1591,7 @@ export function createMultiMap<K, V>(): MultiMap<K, V> {
|
||||
}
|
||||
function multiMapAdd<K, V>(this: MultiMap<K, V>, key: K, value: V) {
|
||||
let values = this.get(key);
|
||||
if (values) {
|
||||
if (values !== undefined) {
|
||||
values.push(value);
|
||||
}
|
||||
else {
|
||||
@@ -1623,7 +1601,7 @@ function multiMapAdd<K, V>(this: MultiMap<K, V>, key: K, value: V) {
|
||||
}
|
||||
function multiMapRemove<K, V>(this: MultiMap<K, V>, key: K, value: V) {
|
||||
const values = this.get(key);
|
||||
if (values) {
|
||||
if (values !== undefined) {
|
||||
unorderedRemoveItem(values, value);
|
||||
if (!values.length) {
|
||||
this.delete(key);
|
||||
@@ -1633,7 +1611,7 @@ function multiMapRemove<K, V>(this: MultiMap<K, V>, key: K, value: V) {
|
||||
|
||||
/** @internal */
|
||||
export function createQueue<T>(items?: readonly T[]): Queue<T> {
|
||||
const elements: (T | undefined)[] = items?.slice() || [];
|
||||
const elements: (T | undefined)[] = items?.slice() ?? [];
|
||||
let headIndex = 0;
|
||||
|
||||
function isEmpty() {
|
||||
@@ -1705,14 +1683,9 @@ export function createSet<TElement, THash = number>(getHashCode: (element: TElem
|
||||
const hash = getHashCode(element);
|
||||
if (!multiMap.has(hash)) return false;
|
||||
const candidates = multiMap.get(hash)!;
|
||||
if (!isArray(candidates)) return equals(candidates, element);
|
||||
if (isArray(candidates)) return contains(candidates, element, equals);
|
||||
|
||||
for (const candidate of candidates) {
|
||||
if (equals(candidate, element)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return equals(candidates, element);
|
||||
},
|
||||
add(element: TElement): Set<TElement> {
|
||||
const hash = getHashCode(element);
|
||||
@@ -1779,6 +1752,8 @@ export function createSet<TElement, THash = number>(getHashCode: (element: TElem
|
||||
return size;
|
||||
},
|
||||
forEach(action: (value: TElement, key: TElement, set: Set<TElement>) => void): void {
|
||||
// NOTE: arrayFrom means that if the callback mutates the underlying collection,
|
||||
// we won't have an accurate set of values
|
||||
for (const elements of arrayFrom(multiMap.values())) {
|
||||
if (isArray(elements)) {
|
||||
for (const element of elements) {
|
||||
@@ -2145,6 +2120,14 @@ export function compareTextSpans(a: Partial<TextSpan> | undefined, b: Partial<Te
|
||||
return compareValues(a?.start, b?.start) || compareValues(a?.length, b?.length);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function maxBy<T>(arr: readonly T[], init: number, mapper: (x: T) => number): number {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
init = Math.max(init, mapper(arr[i]));
|
||||
}
|
||||
return init;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function min<T>(items: readonly [T, ...T[]], compare: Comparer<T>): T;
|
||||
/** @internal */
|
||||
@@ -2270,8 +2253,8 @@ export function setUILocale(value: string | undefined) {
|
||||
* @internal
|
||||
*/
|
||||
export function compareStringsCaseSensitiveUI(a: string, b: string) {
|
||||
const comparer = uiComparerCaseSensitive || (uiComparerCaseSensitive = createUIStringComparer(uiLocale));
|
||||
return comparer(a, b);
|
||||
uiComparerCaseSensitive ??= createUIStringComparer(uiLocale);
|
||||
return uiComparerCaseSensitive(a, b);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -2554,7 +2537,8 @@ export function findBestPatternMatch<T>(values: readonly T[], getPattern: (value
|
||||
// use length of prefix as betterness criteria
|
||||
let longestMatchPrefixLength = -1;
|
||||
|
||||
for (const v of values) {
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
const v = values[i];
|
||||
const pattern = getPattern(v);
|
||||
if (isPatternMatch(pattern, candidate) && pattern.prefix.length > longestMatchPrefixLength) {
|
||||
longestMatchPrefixLength = pattern.prefix.length;
|
||||
@@ -2629,7 +2613,7 @@ export function singleElementArray<T>(t: T | undefined): T[] | undefined {
|
||||
|
||||
/** @internal */
|
||||
export function enumerateInsertsAndDeletes<T, U>(newItems: readonly T[], oldItems: readonly U[], comparer: (a: T, b: U) => Comparison, inserted: (newItem: T) => void, deleted: (oldItem: U) => void, unchanged?: (oldItem: U, newItem: T) => void) {
|
||||
unchanged = unchanged || noop;
|
||||
unchanged ??= noop;
|
||||
let newIndex = 0;
|
||||
let oldIndex = 0;
|
||||
const newLen = newItems.length;
|
||||
@@ -2697,7 +2681,7 @@ export function takeWhile<T, U extends T>(array: readonly T[], predicate: (eleme
|
||||
/** @internal */
|
||||
export function takeWhile<T, U extends T>(array: readonly T[] | undefined, predicate: (element: T) => element is U): U[] | undefined;
|
||||
export function takeWhile<T, U extends T>(array: readonly T[] | undefined, predicate: (element: T) => element is U): U[] | undefined {
|
||||
if (array) {
|
||||
if (array !== undefined) {
|
||||
const len = array.length;
|
||||
let index = 0;
|
||||
while (index < len && predicate(array[index])) {
|
||||
@@ -2713,7 +2697,7 @@ export function skipWhile<T, U extends T>(array: readonly T[], predicate: (eleme
|
||||
export function skipWhile<T, U extends T>(array: readonly T[] | undefined, predicate: (element: T) => element is U): Exclude<T, U>[] | undefined;
|
||||
/** @internal */
|
||||
export function skipWhile<T, U extends T>(array: readonly T[] | undefined, predicate: (element: T) => element is U): Exclude<T, U>[] | undefined {
|
||||
if (array) {
|
||||
if (array !== undefined) {
|
||||
const len = array.length;
|
||||
let index = 0;
|
||||
while (index < len && predicate(array[index])) {
|
||||
|
||||
@@ -61,6 +61,7 @@ import {
|
||||
LiteralType,
|
||||
map,
|
||||
MatchingKeys,
|
||||
maxBy,
|
||||
ModifierFlags,
|
||||
Node,
|
||||
NodeArray,
|
||||
@@ -1126,7 +1127,7 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n")
|
||||
|
||||
function renderGraph() {
|
||||
const columnCount = columnWidths.length;
|
||||
const laneCount = nodes.reduce((x, n) => Math.max(x, n.lane), 0) + 1;
|
||||
const laneCount = maxBy(nodes, 0, n => n.lane) + 1;
|
||||
const lanes: string[] = fill(Array(laneCount), "");
|
||||
const grid: (FlowGraphNode | undefined)[][] = columnWidths.map(() => Array(laneCount));
|
||||
const connectors: Connection[][] = columnWidths.map(() => fill(Array(laneCount), 0));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
append,
|
||||
arraysEqual,
|
||||
arrayIsEqualTo,
|
||||
binarySearch,
|
||||
CharacterCodes,
|
||||
CommentDirective,
|
||||
@@ -475,7 +475,7 @@ export function computePositionOfLineAndCharacter(lineStarts: readonly number[],
|
||||
line = line < 0 ? 0 : line >= lineStarts.length ? lineStarts.length - 1 : line;
|
||||
}
|
||||
else {
|
||||
Debug.fail(`Bad line number. Line: ${line}, lineStarts.length: ${lineStarts.length} , line map is correct? ${debugText !== undefined ? arraysEqual(lineStarts, computeLineStarts(debugText)) : "unknown"}`);
|
||||
Debug.fail(`Bad line number. Line: ${line}, lineStarts.length: ${lineStarts.length} , line map is correct? ${debugText !== undefined ? arrayIsEqualTo(lineStarts, computeLineStarts(debugText)) : "unknown"}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ import {
|
||||
isReferenceFileLocation,
|
||||
isString,
|
||||
last,
|
||||
maxBy,
|
||||
maybeBind,
|
||||
memoize,
|
||||
ModuleKind,
|
||||
@@ -304,7 +305,7 @@ function createTabularErrorsDisplay(filesInError: (ReportFileInError | undefined
|
||||
|
||||
const numberLength = (num: number) => Math.log(num) * Math.LOG10E + 1;
|
||||
const fileToErrorCount = distinctFiles.map(file => ([file, countWhere(filesInError, fileInError => fileInError!.fileName === file!.fileName)] as const));
|
||||
const maxErrors = fileToErrorCount.reduce((acc, value) => Math.max(acc, value[1] || 0), 0);
|
||||
const maxErrors = maxBy(fileToErrorCount, 0, value => value[1]);
|
||||
|
||||
const headerRow = Diagnostics.Errors_Files.message;
|
||||
const leftColumnHeadingLength = headerRow.split(" ")[0].length;
|
||||
|
||||
@@ -2673,17 +2673,12 @@ export class TestState {
|
||||
if (info === undefined) return "No completion info.";
|
||||
const { entries } = info;
|
||||
|
||||
function pad(s: string, length: number) {
|
||||
return s + new Array(length - s.length + 1).join(" ");
|
||||
}
|
||||
function max<T>(arr: T[], selector: (x: T) => number): number {
|
||||
return arr.reduce((prev, x) => Math.max(prev, selector(x)), 0);
|
||||
}
|
||||
const longestNameLength = max(entries, m => m.name.length);
|
||||
const longestKindLength = max(entries, m => m.kind.length);
|
||||
const longestNameLength = ts.maxBy(entries, 0, m => m.name.length);
|
||||
const longestKindLength = ts.maxBy(entries, 0, m => m.kind.length);
|
||||
entries.sort((m, n) => m.sortText > n.sortText ? 1 : m.sortText < n.sortText ? -1 : m.name > n.name ? 1 : m.name < n.name ? -1 : 0);
|
||||
const membersString = entries.map(m => `${pad(m.name, longestNameLength)} ${pad(m.kind, longestKindLength)} ${m.kindModifiers} ${m.isRecommended ? "recommended " : ""}${m.source === undefined ? "" : m.source}`).join("\n");
|
||||
Harness.IO.log(membersString);
|
||||
|
||||
const formattedEntries = entries.map(m => `${m.name.padEnd(longestNameLength)} ${m.kind.padEnd(longestKindLength)} ${m.kindModifiers} ${m.isRecommended ? "recommended " : ""}${m.source ?? ""}`);
|
||||
Harness.IO.log(formattedEntries.join("\n"));
|
||||
}
|
||||
|
||||
public printContext() {
|
||||
|
||||
@@ -77,7 +77,6 @@ import {
|
||||
LanguageServiceMode,
|
||||
length,
|
||||
map,
|
||||
mapDefinedEntries,
|
||||
mapDefinedIterator,
|
||||
missingFileModifiedTime,
|
||||
MultiMap,
|
||||
@@ -4347,14 +4346,15 @@ export class ProjectService {
|
||||
|
||||
/** @internal */
|
||||
loadAncestorProjectTree(forProjects?: ReadonlyCollection<string>) {
|
||||
forProjects = forProjects || mapDefinedEntries(
|
||||
this.configuredProjects,
|
||||
(key, project) => !project.isInitialLoadPending() ? [key, true] : undefined,
|
||||
forProjects ??= new Set(
|
||||
mapDefinedIterator(this.configuredProjects.entries(), ([key, project]) => !project.isInitialLoadPending() ? key : undefined),
|
||||
);
|
||||
|
||||
const seenProjects = new Set<NormalizedPath>();
|
||||
// Work on array copy as we could add more projects as part of callback
|
||||
for (const project of arrayFrom(this.configuredProjects.values())) {
|
||||
// We must copy the current configured projects into a separate array,
|
||||
// as we could end up creating and adding more projects indirectly.
|
||||
const currentConfiguredProjects = arrayFrom(this.configuredProjects.values());
|
||||
for (const project of currentConfiguredProjects) {
|
||||
// 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))) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {
|
||||
arraysEqual,
|
||||
arrayIsEqualTo,
|
||||
ArrowFunction,
|
||||
AssignmentDeclarationKind,
|
||||
BinaryExpression,
|
||||
@@ -222,7 +222,7 @@ export function getJsDocCommentsFromDeclarations(declarations: readonly Declarat
|
||||
}
|
||||
|
||||
function isIdenticalListOfDisplayParts(parts1: SymbolDisplayPart[], parts2: SymbolDisplayPart[]) {
|
||||
return arraysEqual(parts1, parts2, (p1, p2) => p1.kind === p2.kind && p1.text === p2.text);
|
||||
return arrayIsEqualTo(parts1, parts2, (p1, p2) => p1.kind === p2.kind && p1.text === p2.text);
|
||||
}
|
||||
|
||||
function getCommentHavingNodes(declaration: Declaration): readonly (JSDoc | JSDocTag)[] {
|
||||
|
||||
Reference in new issue
Block a user