main
ts 186 lines 3.94 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8 import {NodePath} from '@babel/traverse';
9
10 /*
11 * Trigger an exhaustivess check in TypeScript and throw at runtime.
12 *
13 * Example:
14 *
15 * ```ts
16 * enum ErrorCode = {
17 * E0001 = "E0001",
18 * E0002 = "E0002"
19 * }
20 *
21 * switch (code) {
22 * case ErrorCode.E0001:
23 * // ...
24 * default:
25 * assertExhaustive(code, "Unhandled error code");
26 * }
27 * ```
28 */
29 export function assertExhaustive(_: never, errorMsg: string): never {
30 throw new Error(errorMsg);
31 }
32
33 // Modifies @param array in place, retaining only the items where the predicate returns true.
34 export function retainWhere<T>(
35 array: Array<T>,
36 predicate: (item: T, index: number) => boolean,
37 ): void {
38 let writeIndex = 0;
39 for (let readIndex = 0; readIndex < array.length; readIndex++) {
40 const item = array[readIndex];
41 if (predicate(item, readIndex) === true) {
42 array[writeIndex++] = item;
43 }
44 }
45 array.length = writeIndex;
46 }
47
48 export function retainWhere_Set<T>(
49 items: Set<T>,
50 predicate: (item: T) => boolean,
51 ): void {
52 for (const item of items) {
53 if (!predicate(item)) {
54 items.delete(item);
55 }
56 }
57 }
58
59 export function getOrInsertWith<U, V>(
60 m: Map<U, V>,
61 key: U,
62 makeDefault: () => V,
63 ): V {
64 if (m.has(key)) {
65 return m.get(key) as V;
66 } else {
67 const defaultValue = makeDefault();
68 m.set(key, defaultValue);
69 return defaultValue;
70 }
71 }
72
73 export function getOrInsertDefault<U, V>(
74 m: Map<U, V>,
75 key: U,
76 defaultValue: V,
77 ): V {
78 if (m.has(key)) {
79 return m.get(key) as V;
80 } else {
81 m.set(key, defaultValue);
82 return defaultValue;
83 }
84 }
85 export function Set_equal<T>(a: ReadonlySet<T>, b: ReadonlySet<T>): boolean {
86 if (a.size !== b.size) {
87 return false;
88 }
89 for (const item of a) {
90 if (!b.has(item)) {
91 return false;
92 }
93 }
94 return true;
95 }
96
97 export function Set_union<T>(a: ReadonlySet<T>, b: ReadonlySet<T>): Set<T> {
98 const union = new Set<T>(a);
99 for (const item of b) {
100 union.add(item);
101 }
102 return union;
103 }
104
105 export function Set_intersect<T>(sets: Array<ReadonlySet<T>>): Set<T> {
106 if (sets.length === 0 || sets.some(s => s.size === 0)) {
107 return new Set();
108 } else if (sets.length === 1) {
109 return new Set(sets[0]);
110 }
111 const result: Set<T> = new Set();
112 const first = sets[0];
113 outer: for (const e of first) {
114 for (let i = 1; i < sets.length; i++) {
115 if (!sets[i].has(e)) {
116 continue outer;
117 }
118 }
119 result.add(e);
120 }
121 return result;
122 }
123
124 /**
125 * @returns `true` if `a` is a superset of `b`.
126 */
127 export function Set_isSuperset<T>(
128 a: ReadonlySet<T>,
129 b: ReadonlySet<T>,
130 ): boolean {
131 for (const v of b) {
132 if (!a.has(v)) {
133 return false;
134 }
135 }
136 return true;
137 }
138
139 export function Iterable_some<T>(
140 iter: Iterable<T>,
141 pred: (item: T) => boolean,
142 ): boolean {
143 for (const item of iter) {
144 if (pred(item)) {
145 return true;
146 }
147 }
148 return false;
149 }
150
151 export function nonNull<T extends NonNullable<U>, U>(
152 value: T | null | undefined,
153 ): value is T {
154 return value != null;
155 }
156
157 export function Set_filter<T>(
158 source: ReadonlySet<T>,
159 fn: (arg: T) => boolean,
160 ): Set<T> {
161 const result = new Set<T>();
162 for (const entry of source) {
163 if (fn(entry)) {
164 result.add(entry);
165 }
166 }
167 return result;
168 }
169
170 export function hasNode<T>(
171 input: NodePath<T | null | undefined>,
172 ): input is NodePath<NonNullable<T>> {
173 /*
174 * Internal babel is on an older version that does not have hasNode (v7.17)
175 * See https://github.com/babel/babel/pull/13940/files for impl
176 * https://github.com/babel/babel/blob/5ebab544af2f1c6fc6abdaae6f4e5426975c9a16/packages/babel-traverse/src/path/index.ts#L128-L130
177 */
178 return input.node != null;
179 }
180
181 export function hasOwnProperty<T>(
182 obj: T,
183 key: string | number | symbol,
184 ): key is keyof T {
185 return Object.prototype.hasOwnProperty.call(obj, key);
186 }