@eslint-react/var 5.24.0 → 5.24.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +28 -558
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -5,44 +5,6 @@ import { DefinitionType } from "@typescript-eslint/scope-manager";
|
|
|
5
5
|
import { P, isMatching } from "ts-pattern";
|
|
6
6
|
|
|
7
7
|
//#region ../../.pkgs/eff/dist/index.js
|
|
8
|
-
/**
|
|
9
|
-
* Applies a `pipe` method's variadic arguments to an initial value from left
|
|
10
|
-
* to right.
|
|
11
|
-
*
|
|
12
|
-
* **When to use**
|
|
13
|
-
*
|
|
14
|
-
* Use to implement a custom `.pipe(...)` method from JavaScript's `arguments`
|
|
15
|
-
* object.
|
|
16
|
-
*
|
|
17
|
-
* **Details**
|
|
18
|
-
*
|
|
19
|
-
* This helper is intended for implementing `Pipeable.pipe` methods that
|
|
20
|
-
* receive JavaScript's `arguments` object. With no functions it returns the
|
|
21
|
-
* original value; otherwise it feeds each result into the next function.
|
|
22
|
-
*
|
|
23
|
-
* **Example** (Implementing a pipe method)
|
|
24
|
-
*
|
|
25
|
-
* ```ts
|
|
26
|
-
* import { Pipeable } from "effect"
|
|
27
|
-
*
|
|
28
|
-
* class NumberBox {
|
|
29
|
-
* constructor(readonly value: number) {}
|
|
30
|
-
*
|
|
31
|
-
* pipe(..._fns: ReadonlyArray<(value: number) => number>): number {
|
|
32
|
-
* return Pipeable.pipeArguments(this.value, arguments) as number
|
|
33
|
-
* }
|
|
34
|
-
* }
|
|
35
|
-
*
|
|
36
|
-
* const result = new NumberBox(5).pipe(
|
|
37
|
-
* (n) => n + 2,
|
|
38
|
-
* (n) => n * 3
|
|
39
|
-
* )
|
|
40
|
-
* console.log(result) // 21
|
|
41
|
-
* ```
|
|
42
|
-
*
|
|
43
|
-
* @category combinators
|
|
44
|
-
* @since 2.0.0
|
|
45
|
-
*/
|
|
46
8
|
const pipeArguments = (self, args) => {
|
|
47
9
|
switch (args.length) {
|
|
48
10
|
case 0: return self;
|
|
@@ -62,110 +24,14 @@ const pipeArguments = (self, args) => {
|
|
|
62
24
|
}
|
|
63
25
|
}
|
|
64
26
|
};
|
|
65
|
-
/**
|
|
66
|
-
* Reusable prototype that implements `Pipeable.pipe`.
|
|
67
|
-
*
|
|
68
|
-
* **When to use**
|
|
69
|
-
*
|
|
70
|
-
* Use when classes or object prototypes can reuse this value when they need the
|
|
71
|
-
* standard pipe implementation backed by `pipeArguments`.
|
|
72
|
-
*
|
|
73
|
-
* @category prototypes
|
|
74
|
-
* @since 3.15.0
|
|
75
|
-
*/
|
|
76
27
|
const Prototype = { pipe() {
|
|
77
28
|
return pipeArguments(this, arguments);
|
|
78
29
|
} };
|
|
79
|
-
/**
|
|
80
|
-
* Provides a base constructor whose instances implement the standard `Pipeable.pipe`
|
|
81
|
-
* method.
|
|
82
|
-
*
|
|
83
|
-
* **When to use**
|
|
84
|
-
*
|
|
85
|
-
* Use when you need to define a class that supports Effect-style method
|
|
86
|
-
* chaining through `.pipe(...)`.
|
|
87
|
-
*
|
|
88
|
-
* @category constructors
|
|
89
|
-
* @since 3.15.0
|
|
90
|
-
*/
|
|
91
30
|
const Class = (function() {
|
|
92
31
|
function PipeableBase() {}
|
|
93
32
|
PipeableBase.prototype = Prototype;
|
|
94
33
|
return PipeableBase;
|
|
95
34
|
})();
|
|
96
|
-
/**
|
|
97
|
-
* Provides small helpers for defining and reusing TypeScript functions.
|
|
98
|
-
*
|
|
99
|
-
* The main helpers are `pipe` and `flow` for left-to-right composition and
|
|
100
|
-
* `dual` for APIs that support both direct and pipe-friendly call styles. The
|
|
101
|
-
* module also contains small identity, constant, tuple, type-level, and
|
|
102
|
-
* memoization helpers used across the library.
|
|
103
|
-
*
|
|
104
|
-
* @since 2.0.0
|
|
105
|
-
*/
|
|
106
|
-
/**
|
|
107
|
-
* Creates a function that can be called in data-first style or data-last
|
|
108
|
-
* (`pipe`-friendly) style.
|
|
109
|
-
*
|
|
110
|
-
* **When to use**
|
|
111
|
-
*
|
|
112
|
-
* Use to expose one implementation through both direct and `pipe`-friendly
|
|
113
|
-
* call styles.
|
|
114
|
-
*
|
|
115
|
-
* **Details**
|
|
116
|
-
*
|
|
117
|
-
* Pass either the arity of the uncurried function or a predicate that decides
|
|
118
|
-
* whether the current call is data-first. Arity is the common case. Use a
|
|
119
|
-
* predicate when optional arguments make arity ambiguous.
|
|
120
|
-
*
|
|
121
|
-
* **Example** (Selecting data-first or data-last style by arity)
|
|
122
|
-
*
|
|
123
|
-
* ```ts
|
|
124
|
-
* import { Function, pipe } from "effect"
|
|
125
|
-
*
|
|
126
|
-
* const sum = Function.dual<
|
|
127
|
-
* (that: number) => (self: number) => number,
|
|
128
|
-
* (self: number, that: number) => number
|
|
129
|
-
* >(2, (self, that) => self + that)
|
|
130
|
-
*
|
|
131
|
-
* console.log(sum(2, 3)) // 5
|
|
132
|
-
* console.log(pipe(2, sum(3))) // 5
|
|
133
|
-
* ```
|
|
134
|
-
*
|
|
135
|
-
* **Example** (Defining overloads with call signatures)
|
|
136
|
-
*
|
|
137
|
-
* ```ts
|
|
138
|
-
* import { Function, pipe } from "effect"
|
|
139
|
-
*
|
|
140
|
-
* const sum: {
|
|
141
|
-
* (that: number): (self: number) => number
|
|
142
|
-
* (self: number, that: number): number
|
|
143
|
-
* } = Function.dual(2, (self: number, that: number): number => self + that)
|
|
144
|
-
*
|
|
145
|
-
* console.log(sum(2, 3)) // 5
|
|
146
|
-
* console.log(pipe(2, sum(3))) // 5
|
|
147
|
-
* ```
|
|
148
|
-
*
|
|
149
|
-
* **Example** (Selecting data-first or data-last style with a predicate)
|
|
150
|
-
*
|
|
151
|
-
* ```ts
|
|
152
|
-
* import { Function, pipe } from "effect"
|
|
153
|
-
*
|
|
154
|
-
* const sum = Function.dual<
|
|
155
|
-
* (that: number) => (self: number) => number,
|
|
156
|
-
* (self: number, that: number) => number
|
|
157
|
-
* >(
|
|
158
|
-
* (args) => args.length === 2,
|
|
159
|
-
* (self, that) => self + that
|
|
160
|
-
* )
|
|
161
|
-
*
|
|
162
|
-
* console.log(sum(2, 3)) // 5
|
|
163
|
-
* console.log(pipe(2, sum(3))) // 5
|
|
164
|
-
* ```
|
|
165
|
-
*
|
|
166
|
-
* @category combinators
|
|
167
|
-
* @since 2.0.0
|
|
168
|
-
*/
|
|
169
35
|
const dual = function(arity, body) {
|
|
170
36
|
if (typeof arity === "function") return function() {
|
|
171
37
|
return arity(arguments) ? body.apply(this, arguments) : ((self) => body(self, ...arguments));
|
|
@@ -194,323 +60,55 @@ const dual = function(arity, body) {
|
|
|
194
60
|
};
|
|
195
61
|
}
|
|
196
62
|
};
|
|
197
|
-
/**
|
|
198
|
-
* Returns its input argument unchanged.
|
|
199
|
-
*
|
|
200
|
-
* **When to use**
|
|
201
|
-
*
|
|
202
|
-
* Use to return a value unchanged where a function is required.
|
|
203
|
-
*
|
|
204
|
-
* **Example** (Returning the same value)
|
|
205
|
-
*
|
|
206
|
-
* ```ts
|
|
207
|
-
* import { identity } from "effect"
|
|
208
|
-
* import * as assert from "node:assert"
|
|
209
|
-
*
|
|
210
|
-
* assert.deepStrictEqual(identity(5), 5)
|
|
211
|
-
* ```
|
|
212
|
-
*
|
|
213
|
-
* @category combinators
|
|
214
|
-
* @since 2.0.0
|
|
215
|
-
*/
|
|
216
63
|
const identity = (a) => a;
|
|
217
|
-
/**
|
|
218
|
-
* Returns the input value with a different static type.
|
|
219
|
-
*
|
|
220
|
-
* **When to use**
|
|
221
|
-
*
|
|
222
|
-
* Use when you need an explicit type-level cast and accept that the value is
|
|
223
|
-
* returned unchanged at runtime.
|
|
224
|
-
*
|
|
225
|
-
* **Gotchas**
|
|
226
|
-
*
|
|
227
|
-
* This is a type-level cast only; it performs no runtime validation or
|
|
228
|
-
* conversion.
|
|
229
|
-
*
|
|
230
|
-
* @see {@link satisfies} for checking assignability without changing the resulting type
|
|
231
|
-
*
|
|
232
|
-
* @category utility types
|
|
233
|
-
* @since 4.0.0
|
|
234
|
-
*/
|
|
235
64
|
const cast = identity;
|
|
236
|
-
/**
|
|
237
|
-
* Creates a zero-argument function that always returns the provided value.
|
|
238
|
-
*
|
|
239
|
-
* **When to use**
|
|
240
|
-
*
|
|
241
|
-
* Use when you need a thunk or callback that returns the same value on every
|
|
242
|
-
* invocation.
|
|
243
|
-
*
|
|
244
|
-
* **Example** (Creating a constant thunk)
|
|
245
|
-
*
|
|
246
|
-
* ```ts
|
|
247
|
-
* import { Function } from "effect"
|
|
248
|
-
* import * as assert from "node:assert"
|
|
249
|
-
*
|
|
250
|
-
* const constNull = Function.constant(null)
|
|
251
|
-
*
|
|
252
|
-
* assert.deepStrictEqual(constNull(), null)
|
|
253
|
-
* assert.deepStrictEqual(constNull(), null)
|
|
254
|
-
* ```
|
|
255
|
-
*
|
|
256
|
-
* @category constructors
|
|
257
|
-
* @since 2.0.0
|
|
258
|
-
*/
|
|
259
65
|
const constant = (value) => () => value;
|
|
260
|
-
/**
|
|
261
|
-
* Returns `true` when called.
|
|
262
|
-
*
|
|
263
|
-
* **When to use**
|
|
264
|
-
*
|
|
265
|
-
* Use when you need a thunk that returns `true` on every invocation.
|
|
266
|
-
*
|
|
267
|
-
* **Example** (Returning true from a thunk)
|
|
268
|
-
*
|
|
269
|
-
* ```ts
|
|
270
|
-
* import { Function } from "effect"
|
|
271
|
-
* import * as assert from "node:assert"
|
|
272
|
-
*
|
|
273
|
-
* assert.deepStrictEqual(Function.constTrue(), true)
|
|
274
|
-
* ```
|
|
275
|
-
*
|
|
276
|
-
* @category constants
|
|
277
|
-
* @since 2.0.0
|
|
278
|
-
*/
|
|
279
66
|
const constTrue = constant(true);
|
|
280
|
-
/**
|
|
281
|
-
* Returns `false` when called.
|
|
282
|
-
*
|
|
283
|
-
* **When to use**
|
|
284
|
-
*
|
|
285
|
-
* Use when you need a thunk that returns `false` on every invocation.
|
|
286
|
-
*
|
|
287
|
-
* **Example** (Returning false from a thunk)
|
|
288
|
-
*
|
|
289
|
-
* ```ts
|
|
290
|
-
* import { Function } from "effect"
|
|
291
|
-
* import * as assert from "node:assert"
|
|
292
|
-
*
|
|
293
|
-
* assert.deepStrictEqual(Function.constFalse(), false)
|
|
294
|
-
* ```
|
|
295
|
-
*
|
|
296
|
-
* @category constants
|
|
297
|
-
* @since 2.0.0
|
|
298
|
-
*/
|
|
299
67
|
const constFalse = constant(false);
|
|
300
|
-
/**
|
|
301
|
-
* Returns `null` when called.
|
|
302
|
-
*
|
|
303
|
-
* **When to use**
|
|
304
|
-
*
|
|
305
|
-
* Use when you need a thunk that returns `null` on every invocation.
|
|
306
|
-
*
|
|
307
|
-
* **Example** (Returning null from a thunk)
|
|
308
|
-
*
|
|
309
|
-
* ```ts
|
|
310
|
-
* import { Function } from "effect"
|
|
311
|
-
* import * as assert from "node:assert"
|
|
312
|
-
*
|
|
313
|
-
* assert.deepStrictEqual(Function.constNull(), null)
|
|
314
|
-
* ```
|
|
315
|
-
*
|
|
316
|
-
* @category constants
|
|
317
|
-
* @since 2.0.0
|
|
318
|
-
*/
|
|
319
68
|
const constNull = constant(null);
|
|
320
|
-
/**
|
|
321
|
-
* Returns `undefined` when called.
|
|
322
|
-
*
|
|
323
|
-
* **When to use**
|
|
324
|
-
*
|
|
325
|
-
* Use when you need a thunk that returns `undefined` on every invocation.
|
|
326
|
-
*
|
|
327
|
-
* **Example** (Returning undefined from a thunk)
|
|
328
|
-
*
|
|
329
|
-
* ```ts
|
|
330
|
-
* import { Function } from "effect"
|
|
331
|
-
* import * as assert from "node:assert"
|
|
332
|
-
*
|
|
333
|
-
* assert.deepStrictEqual(Function.constUndefined(), undefined)
|
|
334
|
-
* ```
|
|
335
|
-
*
|
|
336
|
-
* @category constants
|
|
337
|
-
* @since 2.0.0
|
|
338
|
-
*/
|
|
339
69
|
const constUndefined = constant(void 0);
|
|
340
|
-
/**
|
|
341
|
-
* Composes two functions, `ab` and `bc` into a single function that takes in an argument `a` of type `A` and returns a result of type `C`.
|
|
342
|
-
* The result is obtained by first applying the `ab` function to `a` and then applying the `bc` function to the result of `ab`.
|
|
343
|
-
*
|
|
344
|
-
* **When to use**
|
|
345
|
-
*
|
|
346
|
-
* Use to compose exactly two unary functions into a reusable unary function.
|
|
347
|
-
*
|
|
348
|
-
* **Example** (Composing two functions)
|
|
349
|
-
*
|
|
350
|
-
* ```ts
|
|
351
|
-
* import { Function } from "effect"
|
|
352
|
-
* import * as assert from "node:assert"
|
|
353
|
-
*
|
|
354
|
-
* const increment = (n: number) => n + 1
|
|
355
|
-
* const square = (n: number) => n * n
|
|
356
|
-
*
|
|
357
|
-
* assert.strictEqual(Function.compose(increment, square)(2), 9)
|
|
358
|
-
* ```
|
|
359
|
-
*
|
|
360
|
-
* @see {@link flow} for composing a left-to-right sequence of functions
|
|
361
|
-
* @see {@link pipe} for applying a value through a left-to-right sequence immediately
|
|
362
|
-
*
|
|
363
|
-
* @category combinators
|
|
364
|
-
* @since 2.0.0
|
|
365
|
-
*/
|
|
366
70
|
const compose = dual(2, (ab, bc) => (a) => bc(ab(a)));
|
|
367
|
-
/**
|
|
368
|
-
* Marks an impossible branch by accepting a `never` value and returning any
|
|
369
|
-
* type.
|
|
370
|
-
*
|
|
371
|
-
* **When to use**
|
|
372
|
-
*
|
|
373
|
-
* Use when you need a return value in a branch that exhaustive checks prove
|
|
374
|
-
* cannot be reached.
|
|
375
|
-
*
|
|
376
|
-
* **Gotchas**
|
|
377
|
-
*
|
|
378
|
-
* Calling `absurd` throws, because a value of type `never` should be
|
|
379
|
-
* impossible at runtime.
|
|
380
|
-
*
|
|
381
|
-
* **Example** (Handling impossible values)
|
|
382
|
-
*
|
|
383
|
-
* ```ts
|
|
384
|
-
* import { absurd } from "effect"
|
|
385
|
-
*
|
|
386
|
-
* const handleNever = (value: never) => {
|
|
387
|
-
* return absurd(value) // This will throw an error if called
|
|
388
|
-
* }
|
|
389
|
-
* ```
|
|
390
|
-
*
|
|
391
|
-
* @category utility types
|
|
392
|
-
* @since 2.0.0
|
|
393
|
-
*/
|
|
394
71
|
const absurd = (_) => {
|
|
395
72
|
throw new Error("Called `absurd` function which should be uncallable");
|
|
396
73
|
};
|
|
397
|
-
/**
|
|
398
|
-
* Creates a compile-time placeholder for a value of any type.
|
|
399
|
-
*
|
|
400
|
-
* **When to use**
|
|
401
|
-
*
|
|
402
|
-
* Use as a temporary typed placeholder while developing incomplete code.
|
|
403
|
-
*
|
|
404
|
-
* **Gotchas**
|
|
405
|
-
*
|
|
406
|
-
* `hole` is intended for temporary development use. If the placeholder is
|
|
407
|
-
* evaluated at runtime, it throws.
|
|
408
|
-
*
|
|
409
|
-
* **Example** (Creating a development placeholder)
|
|
410
|
-
*
|
|
411
|
-
* ```ts
|
|
412
|
-
* import { hole } from "effect"
|
|
413
|
-
*
|
|
414
|
-
* // Intentionally not called: `hole` throws if the placeholder is evaluated.
|
|
415
|
-
* const buildUser = (id: number): { readonly id: number; readonly name: string } => ({
|
|
416
|
-
* id,
|
|
417
|
-
* name: hole<string>()
|
|
418
|
-
* })
|
|
419
|
-
*
|
|
420
|
-
* console.log(typeof buildUser) // "function"
|
|
421
|
-
* ```
|
|
422
|
-
*
|
|
423
|
-
* @category utility types
|
|
424
|
-
* @since 2.0.0
|
|
425
|
-
*/
|
|
426
74
|
const hole = cast(absurd);
|
|
75
|
+
const and = dual(2, (a, b) => (data) => a(data) && b(data));
|
|
76
|
+
const or = dual(2, (a, b) => (data) => a(data) || b(data));
|
|
77
|
+
const xor = dual(2, (a, b) => (data) => a(data) !== b(data));
|
|
78
|
+
const eqv = dual(2, (a, b) => (data) => a(data) === b(data));
|
|
79
|
+
const implies = dual(2, (antecedent, consequent) => (data) => !antecedent(data) || consequent(data));
|
|
80
|
+
const nor = dual(2, (a, b) => (data) => !a(data) && !b(data));
|
|
81
|
+
const nand = dual(2, (a, b) => (data) => !a(data) || !b(data));
|
|
82
|
+
function isFunction(input) {
|
|
83
|
+
return typeof input === "function";
|
|
84
|
+
}
|
|
85
|
+
function isObjectKeyword(input) {
|
|
86
|
+
return typeof input === "object" && input !== null || isFunction(input);
|
|
87
|
+
}
|
|
88
|
+
const hasProperty = dual(2, (data, property) => isObjectKeyword(data) && property in data);
|
|
427
89
|
function getOrInsertComputed(map, key, callback) {
|
|
428
90
|
if (map.has(key)) return map.get(key);
|
|
429
91
|
const value = callback(key);
|
|
430
92
|
map.set(key, value);
|
|
431
93
|
return value;
|
|
432
94
|
}
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
* Supports both data-first and data-last (`pipe`-friendly) call styles.
|
|
437
|
-
*
|
|
438
|
-
* @param pred - The predicate to test each element with.
|
|
439
|
-
* @returns A new array without the matching prefix.
|
|
440
|
-
* @example
|
|
441
|
-
* ```ts
|
|
442
|
-
* import * as assert from "node:assert"
|
|
443
|
-
* import { dropWhile, pipe } from "@local/eff"
|
|
444
|
-
*
|
|
445
|
-
* // data-first
|
|
446
|
-
* assert.deepStrictEqual(dropWhile([1, 2, 3, 2, 1], (n: number) => n < 3), [3, 2, 1])
|
|
447
|
-
*
|
|
448
|
-
* // data-last
|
|
449
|
-
* assert.deepStrictEqual(pipe([1, 2, 3, 2, 1], dropWhile((n: number) => n < 3)), [3, 2, 1])
|
|
450
|
-
* ```
|
|
451
|
-
* @category array
|
|
452
|
-
*/
|
|
453
|
-
const dropWhile = dual(2, (xs, pred) => {
|
|
454
|
-
const len = xs.length;
|
|
95
|
+
const dropWhile = dual(2, (self, predicate) => {
|
|
96
|
+
const input = Array.isArray(self) ? self : Array.from(self);
|
|
97
|
+
const len = input.length;
|
|
455
98
|
let idx = 0;
|
|
456
|
-
while (idx < len &&
|
|
457
|
-
return
|
|
99
|
+
while (idx < len && predicate(input[idx], idx)) idx++;
|
|
100
|
+
return input.slice(idx);
|
|
458
101
|
});
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
* Supports both data-first and data-last (`pipe`-friendly) call styles.
|
|
463
|
-
*
|
|
464
|
-
* @param pred - The predicate to test each element with.
|
|
465
|
-
* @returns A new array containing only the matching prefix.
|
|
466
|
-
* @example
|
|
467
|
-
* ```ts
|
|
468
|
-
* import * as assert from "node:assert"
|
|
469
|
-
* import { pipe, takeWhile } from "@local/eff"
|
|
470
|
-
*
|
|
471
|
-
* // data-first
|
|
472
|
-
* assert.deepStrictEqual(takeWhile([1, 2, 3, 2, 1], (n: number) => n < 3), [1, 2])
|
|
473
|
-
*
|
|
474
|
-
* // data-last
|
|
475
|
-
* assert.deepStrictEqual(pipe([1, 2, 3, 2, 1], takeWhile((n: number) => n < 3)), [1, 2])
|
|
476
|
-
* ```
|
|
477
|
-
* @category array
|
|
478
|
-
*/
|
|
479
|
-
const takeWhile = dual(2, (xs, pred) => {
|
|
480
|
-
const len = xs.length;
|
|
102
|
+
const takeWhile = dual(2, (self, predicate) => {
|
|
103
|
+
const input = Array.isArray(self) ? self : Array.from(self);
|
|
104
|
+
const len = input.length;
|
|
481
105
|
let idx = 0;
|
|
482
|
-
while (idx < len &&
|
|
483
|
-
return
|
|
106
|
+
while (idx < len && predicate(input[idx], idx)) idx++;
|
|
107
|
+
return input.slice(0, idx);
|
|
484
108
|
});
|
|
485
109
|
|
|
486
110
|
//#endregion
|
|
487
111
|
//#region src/create-import-lookup.ts
|
|
488
|
-
/**
|
|
489
|
-
* Create a lookup of local import bindings from a source by scanning the
|
|
490
|
-
* top-level imports of a program.
|
|
491
|
-
*
|
|
492
|
-
* Entries are kept in source order, and both indexes (by local name and by
|
|
493
|
-
* imported name) are built during the same scan, so every query works
|
|
494
|
-
* immediately after creation. Aliases (`import { flushSync as fs }`) are
|
|
495
|
-
* handled naturally: the alias is the entry's local name.
|
|
496
|
-
*
|
|
497
|
-
* @param program - The program whose top-level import declarations to scan.
|
|
498
|
-
* @param options - The source to track and optional builtin namespaces.
|
|
499
|
-
* @returns An {@link ImportLookup} over the matching import bindings.
|
|
500
|
-
*
|
|
501
|
-
* @example
|
|
502
|
-
* ```typescript
|
|
503
|
-
* const imports = createImportLookup(context.sourceCode.ast, { source: "react-dom" });
|
|
504
|
-
* return {
|
|
505
|
-
* CallExpression(node) {
|
|
506
|
-
* const callee = Extract.unwrap(node.callee);
|
|
507
|
-
* if (Check.isIdentifier(callee) && imports.has(callee.name, "flushSync")) {
|
|
508
|
-
* // ...
|
|
509
|
-
* }
|
|
510
|
-
* },
|
|
511
|
-
* };
|
|
512
|
-
* ```
|
|
513
|
-
*/
|
|
514
112
|
function createImportLookup(program, options) {
|
|
515
113
|
const { builtinNamespaces = [], source } = options;
|
|
516
114
|
const entries = [];
|
|
@@ -584,47 +182,6 @@ function createImportLookup(program, options) {
|
|
|
584
182
|
|
|
585
183
|
//#endregion
|
|
586
184
|
//#region src/resolve-origin.ts
|
|
587
|
-
/**
|
|
588
|
-
* Resolve an identifier to the AST node its value **originates from**,
|
|
589
|
-
* suitable for origin/pedigree tracking in ESLint rule analysis.
|
|
590
|
-
*
|
|
591
|
-
* The resolution follows these rules per definition type:
|
|
592
|
-
*
|
|
593
|
-
* | Definition type | `def.node` | Returns |
|
|
594
|
-
* |--------------------------|----------------------------------------------|------------------------------------|
|
|
595
|
-
* | `CatchClause` | `CatchClause` | `null` |
|
|
596
|
-
* | `ClassName` | `ClassDeclaration` / `ClassExpression` | `def.node` |
|
|
597
|
-
* | `FunctionName` | `FunctionDeclaration` / `FunctionExpression` | `def.node` |
|
|
598
|
-
* | `ImplicitGlobalVariable` | any node | `null` |
|
|
599
|
-
* | `ImportBinding` | import specifier | `def.node` (the import specifier) |
|
|
600
|
-
* | `Parameter` | containing function node | `def.node` (if a real function) |
|
|
601
|
-
* | `TSEnumMember` | `TSEnumMember` | `def.node.initializer` (or `null`) |
|
|
602
|
-
* | `TSEnumName` | `TSEnumDeclaration` | `def.node` |
|
|
603
|
-
* | `TSModuleName` | `TSModuleDeclaration` | `null` |
|
|
604
|
-
* | `Type` | type alias node | `null` |
|
|
605
|
-
* | `Variable` | `VariableDeclarator` | `def.node.init` (or `null`), including for destructured bindings |
|
|
606
|
-
*
|
|
607
|
-
* Unlike {@link resolve}, a binding declared through a destructuring
|
|
608
|
-
* pattern (e.g. `setState` in `const [state, setState] = useState()`) resolves to the
|
|
609
|
-
* declarator's initializer (the `useState()` call), i.e. the source expression the
|
|
610
|
-
* binding derives from rather than the binding's own value; and a parameter resolves
|
|
611
|
-
* to the containing function node (the binding's declaration site) instead of `null`;
|
|
612
|
-
* and an import binding resolves to its import specifier (whose parent
|
|
613
|
-
* `ImportDeclaration` carries the module source) instead of `null`.
|
|
614
|
-
*
|
|
615
|
-
* Use this for origin/pedigree tracking ("what produced this value?"); use
|
|
616
|
-
* {@link resolve} when the precise value of the binding is needed.
|
|
617
|
-
*
|
|
618
|
-
* @param context The ESLint rule context.
|
|
619
|
-
* @param node The identifier to resolve.
|
|
620
|
-
* @param options Optional settings:
|
|
621
|
-
* - `at`: Index of the definition to resolve (default: `0` for the first definition).
|
|
622
|
-
* - `localOnly`: If `true`, only consider variables declared in the same scope as the identifier
|
|
623
|
-
* (this will miss variables declared in an outer scope). When `false` (default), traverse the
|
|
624
|
-
* scope chain upward via `findVariable` so that references to outer-scope bindings are resolved
|
|
625
|
-
* correctly.
|
|
626
|
-
* @returns The resolved origin node, or `null` if the identifier cannot be resolved.
|
|
627
|
-
*/
|
|
628
185
|
function resolveOrigin(context, node, options) {
|
|
629
186
|
const { at = 0, localOnly = false } = options ?? {};
|
|
630
187
|
const scope = context.sourceCode.getScope(node);
|
|
@@ -638,7 +195,7 @@ function resolveOrigin(context, node, options) {
|
|
|
638
195
|
case DefinitionType.Variable: {
|
|
639
196
|
const { init } = def.node;
|
|
640
197
|
if (init == null) return null;
|
|
641
|
-
if ("declarations"
|
|
198
|
+
if (hasProperty(init, "declarations")) return null;
|
|
642
199
|
return init;
|
|
643
200
|
}
|
|
644
201
|
case DefinitionType.Parameter: return Check.isFunction(def.node) ? def.node : null;
|
|
@@ -661,13 +218,6 @@ const thisBlockTypes = [
|
|
|
661
218
|
AST_NODE_TYPES.ClassBody,
|
|
662
219
|
AST_NODE_TYPES.Program
|
|
663
220
|
];
|
|
664
|
-
/**
|
|
665
|
-
* Check if two nodes have equal values.
|
|
666
|
-
* @param context The ESLint rule context.
|
|
667
|
-
* @param a The first node to compare.
|
|
668
|
-
* @param b The second node to compare.
|
|
669
|
-
* @returns `true` if the two nodes have equal values.
|
|
670
|
-
*/
|
|
671
221
|
function isValueEqual(context, a, b) {
|
|
672
222
|
a = Check.isTypeExpression(a) ? Extract.unwrap(a) : a;
|
|
673
223
|
b = Check.isTypeExpression(b) ? Extract.unwrap(b) : b;
|
|
@@ -723,14 +273,6 @@ function isValueEqual(context, a, b) {
|
|
|
723
273
|
|
|
724
274
|
//#endregion
|
|
725
275
|
//#region src/is-assignment-target-equal.ts
|
|
726
|
-
/**
|
|
727
|
-
* Check if two assignment targets are equal, either directly or by their values.
|
|
728
|
-
* @param context The ESLint rule context.
|
|
729
|
-
* @param a The first node to compare.
|
|
730
|
-
* @param b The second node to compare.
|
|
731
|
-
* @returns `true` if the assignment targets are equal.
|
|
732
|
-
* @internal
|
|
733
|
-
*/
|
|
734
276
|
function isAssignmentTargetEqual(context, a, b) {
|
|
735
277
|
const unwrappedA = Check.isTypeExpression(a) ? Extract.unwrap(a) : a;
|
|
736
278
|
const unwrappedB = Check.isTypeExpression(b) ? Extract.unwrap(b) : b;
|
|
@@ -740,11 +282,6 @@ function isAssignmentTargetEqual(context, a, b) {
|
|
|
740
282
|
|
|
741
283
|
//#endregion
|
|
742
284
|
//#region src/resolve-import-source.ts
|
|
743
|
-
/**
|
|
744
|
-
* Get the arguments of a require expression.
|
|
745
|
-
* @param node The node to check.
|
|
746
|
-
* @returns The require expression arguments, or `null` when the node is not a require expression.
|
|
747
|
-
*/
|
|
748
285
|
function getRequireExpressionArguments(node) {
|
|
749
286
|
const expr = Extract.unwrap(node);
|
|
750
287
|
if (expr.type === AST_NODE_TYPES.CallExpression) {
|
|
@@ -755,13 +292,6 @@ function getRequireExpressionArguments(node) {
|
|
|
755
292
|
if (expr.type === AST_NODE_TYPES.MemberExpression) return getRequireExpressionArguments(expr.object);
|
|
756
293
|
return null;
|
|
757
294
|
}
|
|
758
|
-
/**
|
|
759
|
-
* Resolve the import source of a variable by walking its latest definition.
|
|
760
|
-
* @param name The variable name.
|
|
761
|
-
* @param initialScope The initial scope.
|
|
762
|
-
* @param seen The set of already visited variable names (for cycle detection).
|
|
763
|
-
* @returns The import source, or `null` when it cannot be resolved.
|
|
764
|
-
*/
|
|
765
295
|
function resolveImportSource(name, initialScope, seen = /* @__PURE__ */ new Set()) {
|
|
766
296
|
if (seen.has(name)) return null;
|
|
767
297
|
seen.add(name);
|
|
@@ -785,28 +315,12 @@ function resolveImportSource(name, initialScope, seen = /* @__PURE__ */ new Set(
|
|
|
785
315
|
|
|
786
316
|
//#endregion
|
|
787
317
|
//#region src/is-initialized-from-react.ts
|
|
788
|
-
/**
|
|
789
|
-
* Check if a variable is initialized from a React import.
|
|
790
|
-
* @param name The variable name.
|
|
791
|
-
* @param initialScope The initial scope.
|
|
792
|
-
* @param importSource Alternative import source of React (ex: "preact/compat").
|
|
793
|
-
* @returns `true` if the variable is initialized or derived from a React import.
|
|
794
|
-
* @internal
|
|
795
|
-
*/
|
|
796
318
|
function isInitializedFromReact(name, initialScope, importSource = "react") {
|
|
797
319
|
return name.toLowerCase() === "react" || Boolean(resolveImportSource(name, initialScope)?.startsWith(importSource));
|
|
798
320
|
}
|
|
799
321
|
|
|
800
322
|
//#endregion
|
|
801
323
|
//#region src/is-initialized-from-react-native.ts
|
|
802
|
-
/**
|
|
803
|
-
* Check if a variable is initialized from a React Native import.
|
|
804
|
-
* @param name The variable name.
|
|
805
|
-
* @param initialScope The initial scope.
|
|
806
|
-
* @param importSource Alternative import source of React Native (ex: "react-native-web").
|
|
807
|
-
* @returns `true` if the variable is initialized or derived from a React Native import.
|
|
808
|
-
* @internal
|
|
809
|
-
*/
|
|
810
324
|
function isInitializedFromReactNative(name, initialScope, importSource = "react-native") {
|
|
811
325
|
return [
|
|
812
326
|
"react_native",
|
|
@@ -817,39 +331,6 @@ function isInitializedFromReactNative(name, initialScope, importSource = "react-
|
|
|
817
331
|
|
|
818
332
|
//#endregion
|
|
819
333
|
//#region src/resolve.ts
|
|
820
|
-
/**
|
|
821
|
-
* Resolve an identifier to the AST node that represents its value,
|
|
822
|
-
* suitable for use in ESLint rule analysis.
|
|
823
|
-
*
|
|
824
|
-
* The resolution follows these rules per definition type:
|
|
825
|
-
*
|
|
826
|
-
* | Definition type | `def.node` | Returns |
|
|
827
|
-
* |--------------------------|----------------------------------------------|------------------------------------|
|
|
828
|
-
* | `CatchClause` | `CatchClause` | `null` |
|
|
829
|
-
* | `ClassName` | `ClassDeclaration` / `ClassExpression` | `def.node` |
|
|
830
|
-
* | `FunctionName` | `FunctionDeclaration` / `FunctionExpression` | `def.node` |
|
|
831
|
-
* | `ImplicitGlobalVariable` | any node | `null` |
|
|
832
|
-
* | `ImportBinding` | import specifier | `null` |
|
|
833
|
-
* | `Parameter` | containing function node | `null` (the value is supplied by the caller) |
|
|
834
|
-
* | `TSEnumMember` | `TSEnumMember` | `def.node.initializer` (or `null`) |
|
|
835
|
-
* | `TSEnumName` | `TSEnumDeclaration` | `def.node` |
|
|
836
|
-
* | `TSModuleName` | `TSModuleDeclaration` | `null` |
|
|
837
|
-
* | `Type` | type alias node | `null` |
|
|
838
|
-
* | `Variable` | `VariableDeclarator` | `def.node.init` for a plain identifier binding; `null` for destructured bindings or missing init |
|
|
839
|
-
*
|
|
840
|
-
* @param context The ESLint rule context.
|
|
841
|
-
* @param node The identifier to resolve.
|
|
842
|
-
* @param options Optional settings:
|
|
843
|
-
* - `at`: Index of the definition to resolve (default: `0` for the first definition).
|
|
844
|
-
* - `localOnly`: If `true`, only consider variables declared in the same scope as the identifier
|
|
845
|
-
* (this will miss variables declared in an outer scope). When `false` (default), traverse the
|
|
846
|
-
* scope chain upward via `findVariable` so that references to outer-scope bindings are resolved
|
|
847
|
-
* correctly.
|
|
848
|
-
* @returns The resolved node, or `null` if the identifier cannot be resolved to a value node.
|
|
849
|
-
*
|
|
850
|
-
* For origin/pedigree tracking that maps destructured bindings to the declarator's
|
|
851
|
-
* initializer, see {@link resolveOrigin}.
|
|
852
|
-
*/
|
|
853
334
|
function resolve(context, node, options) {
|
|
854
335
|
const { at = 0, localOnly = false } = options ?? {};
|
|
855
336
|
const scope = context.sourceCode.getScope(node);
|
|
@@ -864,7 +345,7 @@ function resolve(context, node, options) {
|
|
|
864
345
|
const { id, init } = def.node;
|
|
865
346
|
if (id !== def.name) return null;
|
|
866
347
|
if (init == null) return null;
|
|
867
|
-
if ("declarations"
|
|
348
|
+
if (hasProperty(init, "declarations")) return null;
|
|
868
349
|
return init;
|
|
869
350
|
}
|
|
870
351
|
case DefinitionType.Parameter: return null;
|
|
@@ -881,11 +362,6 @@ function resolve(context, node, options) {
|
|
|
881
362
|
|
|
882
363
|
//#endregion
|
|
883
364
|
//#region src/resolve-enclosing-assignment-target.ts
|
|
884
|
-
/**
|
|
885
|
-
* Resolve the enclosing assignment target (variable, property, etc.) of the node.
|
|
886
|
-
* @param node The starting node for the upward search.
|
|
887
|
-
* @returns The enclosing assignment target node, or `null` when not found.
|
|
888
|
-
*/
|
|
889
365
|
function resolveEnclosingAssignmentTarget(node) {
|
|
890
366
|
switch (node.type) {
|
|
891
367
|
case AST_NODE_TYPES.VariableDeclarator: return node.id;
|
|
@@ -900,12 +376,6 @@ function resolveEnclosingAssignmentTarget(node) {
|
|
|
900
376
|
|
|
901
377
|
//#endregion
|
|
902
378
|
//#region src/resolve-object-type.ts
|
|
903
|
-
/**
|
|
904
|
-
* Resolve the object type of the node.
|
|
905
|
-
* @param context The ESLint rule context.
|
|
906
|
-
* @param node The node to resolve.
|
|
907
|
-
* @returns The object type of the node, or `null` when it cannot be resolved.
|
|
908
|
-
*/
|
|
909
379
|
function resolveObjectType(context, node) {
|
|
910
380
|
if (node == null) return null;
|
|
911
381
|
switch (node.type) {
|
|
@@ -938,7 +408,7 @@ function resolveObjectType(context, node) {
|
|
|
938
408
|
node
|
|
939
409
|
};
|
|
940
410
|
case AST_NODE_TYPES.Literal:
|
|
941
|
-
if ("regex"
|
|
411
|
+
if (hasProperty(node, "regex")) return {
|
|
942
412
|
kind: "regexp",
|
|
943
413
|
node
|
|
944
414
|
};
|
|
@@ -1002,7 +472,7 @@ function resolveObjectType(context, node) {
|
|
|
1002
472
|
};
|
|
1003
473
|
}
|
|
1004
474
|
default:
|
|
1005
|
-
if (!("expression"
|
|
475
|
+
if (!hasProperty(node, "expression") || typeof node.expression !== "object") return null;
|
|
1006
476
|
return resolveObjectType(context, node.expression);
|
|
1007
477
|
}
|
|
1008
478
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eslint-react/var",
|
|
3
|
-
"version": "5.24.
|
|
3
|
+
"version": "5.24.2",
|
|
4
4
|
"description": "ESLint React's TSESTree AST utility module for static analysis of variables.",
|
|
5
5
|
"homepage": "https://github.com/Rel1cx/eslint-react",
|
|
6
6
|
"bugs": {
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"dist"
|
|
30
30
|
],
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@eslint-react/ast": "5.24.
|
|
33
|
-
"@eslint-react/eslint": "5.24.
|
|
32
|
+
"@eslint-react/ast": "5.24.2",
|
|
33
|
+
"@eslint-react/eslint": "5.24.2",
|
|
34
34
|
"@typescript-eslint/scope-manager": "^8.71.0",
|
|
35
35
|
"@typescript-eslint/types": "^8.71.0",
|
|
36
36
|
"@typescript-eslint/utils": "^8.71.0",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"@local/eff": "0.0.0",
|
|
42
42
|
"@local/testkit": "0.0.0",
|
|
43
43
|
"@typescript-eslint/typescript-estree": "^8.71.0",
|
|
44
|
-
"eslint": "^10.
|
|
44
|
+
"eslint": "^10.12.0",
|
|
45
45
|
"tsdown": "^0.23.0",
|
|
46
46
|
"typescript": "6.0.3",
|
|
47
47
|
"vitest": "^5.0.3"
|