/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ import {NodePath} from '@babel/traverse'; /* * Trigger an exhaustivess check in TypeScript and throw at runtime. * * Example: * * ```ts * enum ErrorCode = { * E0001 = "E0001", * E0002 = "E0002" * } * * switch (code) { * case ErrorCode.E0001: * // ... * default: * assertExhaustive(code, "Unhandled error code"); * } * ``` */ export function assertExhaustive(_: never, errorMsg: string): never { throw new Error(errorMsg); } // Modifies @param array in place, retaining only the items where the predicate returns true. export function retainWhere( array: Array, predicate: (item: T, index: number) => boolean, ): void { let writeIndex = 0; for (let readIndex = 0; readIndex < array.length; readIndex++) { const item = array[readIndex]; if (predicate(item, readIndex) === true) { array[writeIndex++] = item; } } array.length = writeIndex; } export function retainWhere_Set( items: Set, predicate: (item: T) => boolean, ): void { for (const item of items) { if (!predicate(item)) { items.delete(item); } } } export function getOrInsertWith( m: Map, key: U, makeDefault: () => V, ): V { if (m.has(key)) { return m.get(key) as V; } else { const defaultValue = makeDefault(); m.set(key, defaultValue); return defaultValue; } } export function getOrInsertDefault( m: Map, key: U, defaultValue: V, ): V { if (m.has(key)) { return m.get(key) as V; } else { m.set(key, defaultValue); return defaultValue; } } export function Set_equal(a: ReadonlySet, b: ReadonlySet): boolean { if (a.size !== b.size) { return false; } for (const item of a) { if (!b.has(item)) { return false; } } return true; } export function Set_union(a: ReadonlySet, b: ReadonlySet): Set { const union = new Set(a); for (const item of b) { union.add(item); } return union; } export function Set_intersect(sets: Array>): Set { if (sets.length === 0 || sets.some(s => s.size === 0)) { return new Set(); } else if (sets.length === 1) { return new Set(sets[0]); } const result: Set = new Set(); const first = sets[0]; outer: for (const e of first) { for (let i = 1; i < sets.length; i++) { if (!sets[i].has(e)) { continue outer; } } result.add(e); } return result; } /** * @returns `true` if `a` is a superset of `b`. */ export function Set_isSuperset( a: ReadonlySet, b: ReadonlySet, ): boolean { for (const v of b) { if (!a.has(v)) { return false; } } return true; } export function Iterable_some( iter: Iterable, pred: (item: T) => boolean, ): boolean { for (const item of iter) { if (pred(item)) { return true; } } return false; } export function nonNull, U>( value: T | null | undefined, ): value is T { return value != null; } export function Set_filter( source: ReadonlySet, fn: (arg: T) => boolean, ): Set { const result = new Set(); for (const entry of source) { if (fn(entry)) { result.add(entry); } } return result; } export function hasNode( input: NodePath, ): input is NodePath> { /* * Internal babel is on an older version that does not have hasNode (v7.17) * See https://github.com/babel/babel/pull/13940/files for impl * https://github.com/babel/babel/blob/5ebab544af2f1c6fc6abdaae6f4e5426975c9a16/packages/babel-traverse/src/path/index.ts#L128-L130 */ return input.node != null; } export function hasOwnProperty( obj: T, key: string | number | symbol, ): key is keyof T { return Object.prototype.hasOwnProperty.call(obj, key); }