@eslint-react/core 1.28.0-beta.1 → 1.28.0-beta.6
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.d.mts +64 -67
- package/dist/index.d.ts +64 -67
- package/dist/index.js +664 -164
- package/dist/index.mjs +660 -165
- package/package.json +7 -7
package/dist/index.mjs
CHANGED
|
@@ -1,28 +1,490 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as AST8 from '@eslint-react/ast';
|
|
2
2
|
import { flip, dual, constFalse, identity, _ } from '@eslint-react/eff';
|
|
3
3
|
import * as JSX3 from '@eslint-react/jsx';
|
|
4
|
-
import {
|
|
4
|
+
import { DEFAULT_ESLINT_REACT_SETTINGS as DEFAULT_ESLINT_REACT_SETTINGS$1, unsafeDecodeSettings, getId } from '@eslint-react/shared';
|
|
5
5
|
import { AST_NODE_TYPES } from '@typescript-eslint/types';
|
|
6
6
|
import * as VAR from '@eslint-react/var';
|
|
7
7
|
import { match, P } from 'ts-pattern';
|
|
8
8
|
import birecord from 'birecord';
|
|
9
9
|
|
|
10
10
|
// src/component/component-collector.ts
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
|
|
12
|
+
// ../../node_modules/.pnpm/valibot@1.0.0-rc.2_typescript@5.8.1-rc/node_modules/valibot/dist/index.js
|
|
13
|
+
var store;
|
|
14
|
+
// @__NO_SIDE_EFFECTS__
|
|
15
|
+
function getGlobalConfig(config2) {
|
|
16
|
+
return {
|
|
17
|
+
lang: config2?.lang ?? store?.lang,
|
|
18
|
+
message: config2?.message,
|
|
19
|
+
abortEarly: config2?.abortEarly ?? store?.abortEarly,
|
|
20
|
+
abortPipeEarly: config2?.abortPipeEarly ?? store?.abortPipeEarly
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
var store2;
|
|
24
|
+
// @__NO_SIDE_EFFECTS__
|
|
25
|
+
function getGlobalMessage(lang) {
|
|
26
|
+
return store2?.get(lang);
|
|
27
|
+
}
|
|
28
|
+
var store3;
|
|
29
|
+
// @__NO_SIDE_EFFECTS__
|
|
30
|
+
function getSchemaMessage(lang) {
|
|
31
|
+
return store3?.get(lang);
|
|
32
|
+
}
|
|
33
|
+
var store4;
|
|
34
|
+
// @__NO_SIDE_EFFECTS__
|
|
35
|
+
function getSpecificMessage(reference, lang) {
|
|
36
|
+
return store4?.get(reference)?.get(lang);
|
|
37
|
+
}
|
|
38
|
+
// @__NO_SIDE_EFFECTS__
|
|
39
|
+
function _stringify(input) {
|
|
40
|
+
const type = typeof input;
|
|
41
|
+
if (type === "string") {
|
|
42
|
+
return `"${input}"`;
|
|
43
|
+
}
|
|
44
|
+
if (type === "number" || type === "bigint" || type === "boolean") {
|
|
45
|
+
return `${input}`;
|
|
46
|
+
}
|
|
47
|
+
if (type === "object" || type === "function") {
|
|
48
|
+
return (input && Object.getPrototypeOf(input)?.constructor?.name) ?? "null";
|
|
49
|
+
}
|
|
50
|
+
return type;
|
|
51
|
+
}
|
|
52
|
+
function _addIssue(context, label, dataset, config2, other) {
|
|
53
|
+
const input = other && "input" in other ? other.input : dataset.value;
|
|
54
|
+
const expected = other?.expected ?? context.expects ?? null;
|
|
55
|
+
const received = other?.received ?? /* @__PURE__ */ _stringify(input);
|
|
56
|
+
const issue = {
|
|
57
|
+
kind: context.kind,
|
|
58
|
+
type: context.type,
|
|
59
|
+
input,
|
|
60
|
+
expected,
|
|
61
|
+
received,
|
|
62
|
+
message: `Invalid ${label}: ${expected ? `Expected ${expected} but r` : "R"}eceived ${received}`,
|
|
63
|
+
requirement: context.requirement,
|
|
64
|
+
path: other?.path,
|
|
65
|
+
issues: other?.issues,
|
|
66
|
+
lang: config2.lang,
|
|
67
|
+
abortEarly: config2.abortEarly,
|
|
68
|
+
abortPipeEarly: config2.abortPipeEarly
|
|
69
|
+
};
|
|
70
|
+
const isSchema = context.kind === "schema";
|
|
71
|
+
const message = other?.message ?? context.message ?? /* @__PURE__ */ getSpecificMessage(context.reference, issue.lang) ?? (isSchema ? /* @__PURE__ */ getSchemaMessage(issue.lang) : null) ?? config2.message ?? /* @__PURE__ */ getGlobalMessage(issue.lang);
|
|
72
|
+
if (message) {
|
|
73
|
+
issue.message = typeof message === "function" ? (
|
|
74
|
+
// @ts-expect-error
|
|
75
|
+
message(issue)
|
|
76
|
+
) : message;
|
|
77
|
+
}
|
|
78
|
+
if (isSchema) {
|
|
79
|
+
dataset.typed = false;
|
|
80
|
+
}
|
|
81
|
+
if (dataset.issues) {
|
|
82
|
+
dataset.issues.push(issue);
|
|
83
|
+
} else {
|
|
84
|
+
dataset.issues = [issue];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// @__NO_SIDE_EFFECTS__
|
|
88
|
+
function _getStandardProps(context) {
|
|
89
|
+
return {
|
|
90
|
+
version: 1,
|
|
91
|
+
vendor: "valibot",
|
|
92
|
+
validate(value2) {
|
|
93
|
+
return context["~run"]({ value: value2 }, /* @__PURE__ */ getGlobalConfig());
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
var ValiError = class extends Error {
|
|
98
|
+
/**
|
|
99
|
+
* Creates a Valibot error with useful information.
|
|
100
|
+
*
|
|
101
|
+
* @param issues The error issues.
|
|
102
|
+
*/
|
|
103
|
+
constructor(issues) {
|
|
104
|
+
super(issues[0].message);
|
|
105
|
+
this.name = "ValiError";
|
|
106
|
+
this.issues = issues;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
// @__NO_SIDE_EFFECTS__
|
|
110
|
+
function getFallback(schema, dataset, config2) {
|
|
111
|
+
return typeof schema.fallback === "function" ? (
|
|
112
|
+
// @ts-expect-error
|
|
113
|
+
schema.fallback(dataset, config2)
|
|
114
|
+
) : (
|
|
115
|
+
// @ts-expect-error
|
|
116
|
+
schema.fallback
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
// @__NO_SIDE_EFFECTS__
|
|
120
|
+
function getDefault(schema, dataset, config2) {
|
|
121
|
+
return typeof schema.default === "function" ? (
|
|
122
|
+
// @ts-expect-error
|
|
123
|
+
schema.default(dataset, config2)
|
|
124
|
+
) : (
|
|
125
|
+
// @ts-expect-error
|
|
126
|
+
schema.default
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
// @__NO_SIDE_EFFECTS__
|
|
130
|
+
function array(item, message) {
|
|
131
|
+
return {
|
|
132
|
+
kind: "schema",
|
|
133
|
+
type: "array",
|
|
134
|
+
reference: array,
|
|
135
|
+
expects: "Array",
|
|
136
|
+
async: false,
|
|
137
|
+
item,
|
|
138
|
+
message,
|
|
139
|
+
get "~standard"() {
|
|
140
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
141
|
+
},
|
|
142
|
+
"~run"(dataset, config2) {
|
|
143
|
+
const input = dataset.value;
|
|
144
|
+
if (Array.isArray(input)) {
|
|
145
|
+
dataset.typed = true;
|
|
146
|
+
dataset.value = [];
|
|
147
|
+
for (let key = 0; key < input.length; key++) {
|
|
148
|
+
const value2 = input[key];
|
|
149
|
+
const itemDataset = this.item["~run"]({ value: value2 }, config2);
|
|
150
|
+
if (itemDataset.issues) {
|
|
151
|
+
const pathItem = {
|
|
152
|
+
type: "array",
|
|
153
|
+
origin: "value",
|
|
154
|
+
input,
|
|
155
|
+
key,
|
|
156
|
+
value: value2
|
|
157
|
+
};
|
|
158
|
+
for (const issue of itemDataset.issues) {
|
|
159
|
+
if (issue.path) {
|
|
160
|
+
issue.path.unshift(pathItem);
|
|
161
|
+
} else {
|
|
162
|
+
issue.path = [pathItem];
|
|
163
|
+
}
|
|
164
|
+
dataset.issues?.push(issue);
|
|
165
|
+
}
|
|
166
|
+
if (!dataset.issues) {
|
|
167
|
+
dataset.issues = itemDataset.issues;
|
|
168
|
+
}
|
|
169
|
+
if (config2.abortEarly) {
|
|
170
|
+
dataset.typed = false;
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (!itemDataset.typed) {
|
|
175
|
+
dataset.typed = false;
|
|
176
|
+
}
|
|
177
|
+
dataset.value.push(itemDataset.value);
|
|
178
|
+
}
|
|
179
|
+
} else {
|
|
180
|
+
_addIssue(this, "type", dataset, config2);
|
|
181
|
+
}
|
|
182
|
+
return dataset;
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
// @__NO_SIDE_EFFECTS__
|
|
187
|
+
function boolean(message) {
|
|
188
|
+
return {
|
|
189
|
+
kind: "schema",
|
|
190
|
+
type: "boolean",
|
|
191
|
+
reference: boolean,
|
|
192
|
+
expects: "boolean",
|
|
193
|
+
async: false,
|
|
194
|
+
message,
|
|
195
|
+
get "~standard"() {
|
|
196
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
197
|
+
},
|
|
198
|
+
"~run"(dataset, config2) {
|
|
199
|
+
if (typeof dataset.value === "boolean") {
|
|
200
|
+
dataset.typed = true;
|
|
201
|
+
} else {
|
|
202
|
+
_addIssue(this, "type", dataset, config2);
|
|
203
|
+
}
|
|
204
|
+
return dataset;
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
// @__NO_SIDE_EFFECTS__
|
|
209
|
+
function object(entries, message) {
|
|
210
|
+
return {
|
|
211
|
+
kind: "schema",
|
|
212
|
+
type: "object",
|
|
213
|
+
reference: object,
|
|
214
|
+
expects: "Object",
|
|
215
|
+
async: false,
|
|
216
|
+
entries,
|
|
217
|
+
message,
|
|
218
|
+
get "~standard"() {
|
|
219
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
220
|
+
},
|
|
221
|
+
"~run"(dataset, config2) {
|
|
222
|
+
const input = dataset.value;
|
|
223
|
+
if (input && typeof input === "object") {
|
|
224
|
+
dataset.typed = true;
|
|
225
|
+
dataset.value = {};
|
|
226
|
+
for (const key in this.entries) {
|
|
227
|
+
const valueSchema = this.entries[key];
|
|
228
|
+
if (key in input || (valueSchema.type === "exact_optional" || valueSchema.type === "optional" || valueSchema.type === "nullish") && // @ts-expect-error
|
|
229
|
+
valueSchema.default !== void 0) {
|
|
230
|
+
const value2 = key in input ? (
|
|
231
|
+
// @ts-expect-error
|
|
232
|
+
input[key]
|
|
233
|
+
) : /* @__PURE__ */ getDefault(valueSchema);
|
|
234
|
+
const valueDataset = valueSchema["~run"]({ value: value2 }, config2);
|
|
235
|
+
if (valueDataset.issues) {
|
|
236
|
+
const pathItem = {
|
|
237
|
+
type: "object",
|
|
238
|
+
origin: "value",
|
|
239
|
+
input,
|
|
240
|
+
key,
|
|
241
|
+
value: value2
|
|
242
|
+
};
|
|
243
|
+
for (const issue of valueDataset.issues) {
|
|
244
|
+
if (issue.path) {
|
|
245
|
+
issue.path.unshift(pathItem);
|
|
246
|
+
} else {
|
|
247
|
+
issue.path = [pathItem];
|
|
248
|
+
}
|
|
249
|
+
dataset.issues?.push(issue);
|
|
250
|
+
}
|
|
251
|
+
if (!dataset.issues) {
|
|
252
|
+
dataset.issues = valueDataset.issues;
|
|
253
|
+
}
|
|
254
|
+
if (config2.abortEarly) {
|
|
255
|
+
dataset.typed = false;
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (!valueDataset.typed) {
|
|
260
|
+
dataset.typed = false;
|
|
261
|
+
}
|
|
262
|
+
dataset.value[key] = valueDataset.value;
|
|
263
|
+
} else if (valueSchema.fallback !== void 0) {
|
|
264
|
+
dataset.value[key] = /* @__PURE__ */ getFallback(valueSchema);
|
|
265
|
+
} else if (valueSchema.type !== "exact_optional" && valueSchema.type !== "optional" && valueSchema.type !== "nullish") {
|
|
266
|
+
_addIssue(this, "key", dataset, config2, {
|
|
267
|
+
input: void 0,
|
|
268
|
+
expected: `"${key}"`,
|
|
269
|
+
path: [
|
|
270
|
+
{
|
|
271
|
+
type: "object",
|
|
272
|
+
origin: "key",
|
|
273
|
+
input,
|
|
274
|
+
key,
|
|
275
|
+
// @ts-expect-error
|
|
276
|
+
value: input[key]
|
|
277
|
+
}
|
|
278
|
+
]
|
|
279
|
+
});
|
|
280
|
+
if (config2.abortEarly) {
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
} else {
|
|
286
|
+
_addIssue(this, "type", dataset, config2);
|
|
287
|
+
}
|
|
288
|
+
return dataset;
|
|
289
|
+
}
|
|
290
|
+
};
|
|
21
291
|
}
|
|
292
|
+
// @__NO_SIDE_EFFECTS__
|
|
293
|
+
function optional(wrapped, default_) {
|
|
294
|
+
return {
|
|
295
|
+
kind: "schema",
|
|
296
|
+
type: "optional",
|
|
297
|
+
reference: optional,
|
|
298
|
+
expects: `(${wrapped.expects} | undefined)`,
|
|
299
|
+
async: false,
|
|
300
|
+
wrapped,
|
|
301
|
+
default: default_,
|
|
302
|
+
get "~standard"() {
|
|
303
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
304
|
+
},
|
|
305
|
+
"~run"(dataset, config2) {
|
|
306
|
+
if (dataset.value === void 0) {
|
|
307
|
+
if (this.default !== void 0) {
|
|
308
|
+
dataset.value = /* @__PURE__ */ getDefault(this, dataset, config2);
|
|
309
|
+
}
|
|
310
|
+
if (dataset.value === void 0) {
|
|
311
|
+
dataset.typed = true;
|
|
312
|
+
return dataset;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
return this.wrapped["~run"](dataset, config2);
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
// @__NO_SIDE_EFFECTS__
|
|
320
|
+
function string(message) {
|
|
321
|
+
return {
|
|
322
|
+
kind: "schema",
|
|
323
|
+
type: "string",
|
|
324
|
+
reference: string,
|
|
325
|
+
expects: "string",
|
|
326
|
+
async: false,
|
|
327
|
+
message,
|
|
328
|
+
get "~standard"() {
|
|
329
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
330
|
+
},
|
|
331
|
+
"~run"(dataset, config2) {
|
|
332
|
+
if (typeof dataset.value === "string") {
|
|
333
|
+
dataset.typed = true;
|
|
334
|
+
} else {
|
|
335
|
+
_addIssue(this, "type", dataset, config2);
|
|
336
|
+
}
|
|
337
|
+
return dataset;
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
function parse(schema, input, config2) {
|
|
342
|
+
const dataset = schema["~run"]({ value: input }, /* @__PURE__ */ getGlobalConfig(config2));
|
|
343
|
+
if (dataset.issues) {
|
|
344
|
+
throw new ValiError(dataset.issues);
|
|
345
|
+
}
|
|
346
|
+
return dataset.value;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// ../shared/src/schemas.ts
|
|
350
|
+
var CustomComponentPropSchema = object({
|
|
351
|
+
/**
|
|
352
|
+
* The name of the prop in the user-defined component.
|
|
353
|
+
* @example
|
|
354
|
+
* "to"
|
|
355
|
+
*/
|
|
356
|
+
name: string(),
|
|
357
|
+
/**
|
|
358
|
+
* The name of the prop in the built-in component.
|
|
359
|
+
* @example
|
|
360
|
+
* "href"
|
|
361
|
+
*/
|
|
362
|
+
as: optional(string()),
|
|
363
|
+
/**
|
|
364
|
+
* Whether the prop is controlled or not in the user-defined component.
|
|
365
|
+
* @example
|
|
366
|
+
* `true`
|
|
367
|
+
*/
|
|
368
|
+
controlled: optional(boolean()),
|
|
369
|
+
/**
|
|
370
|
+
* The default value of the prop in the user-defined component.
|
|
371
|
+
* @example
|
|
372
|
+
* `"/"`
|
|
373
|
+
*/
|
|
374
|
+
defaultValue: optional(string())
|
|
375
|
+
});
|
|
376
|
+
var CustomComponentSchema = object({
|
|
377
|
+
/**
|
|
378
|
+
* The name of the user-defined component.
|
|
379
|
+
* @example
|
|
380
|
+
* "Link"
|
|
381
|
+
*/
|
|
382
|
+
name: string(),
|
|
383
|
+
/**
|
|
384
|
+
* The name of the built-in component that the user-defined component represents.
|
|
385
|
+
* @example
|
|
386
|
+
* "a"
|
|
387
|
+
*/
|
|
388
|
+
as: optional(string()),
|
|
389
|
+
/**
|
|
390
|
+
* Attributes mapping between the user-defined component and the built-in component.
|
|
391
|
+
* @example
|
|
392
|
+
* `Link` component has a `to` attribute that represents the `href` attribute in the built-in `a` element with a default value of `"/"`.
|
|
393
|
+
*/
|
|
394
|
+
attributes: optional(array(CustomComponentPropSchema)),
|
|
395
|
+
/**
|
|
396
|
+
* The ESQuery selector to select the component precisely.
|
|
397
|
+
* @internal
|
|
398
|
+
* @example
|
|
399
|
+
* `JSXElement:has(JSXAttribute[name.name='component'][value.value='a'])`
|
|
400
|
+
*/
|
|
401
|
+
selector: optional(string())
|
|
402
|
+
});
|
|
403
|
+
var CustomHooksSchema = object({
|
|
404
|
+
use: optional(array(string())),
|
|
405
|
+
useActionState: optional(array(string())),
|
|
406
|
+
useCallback: optional(array(string())),
|
|
407
|
+
useContext: optional(array(string())),
|
|
408
|
+
useDebugValue: optional(array(string())),
|
|
409
|
+
useDeferredValue: optional(array(string())),
|
|
410
|
+
useEffect: optional(array(string())),
|
|
411
|
+
useFormStatus: optional(array(string())),
|
|
412
|
+
useId: optional(array(string())),
|
|
413
|
+
useImperativeHandle: optional(array(string())),
|
|
414
|
+
useInsertionEffect: optional(array(string())),
|
|
415
|
+
useLayoutEffect: optional(array(string())),
|
|
416
|
+
useMemo: optional(array(string())),
|
|
417
|
+
useOptimistic: optional(array(string())),
|
|
418
|
+
useReducer: optional(array(string())),
|
|
419
|
+
useRef: optional(array(string())),
|
|
420
|
+
useState: optional(array(string())),
|
|
421
|
+
useSyncExternalStore: optional(array(string())),
|
|
422
|
+
useTransition: optional(array(string()))
|
|
423
|
+
});
|
|
424
|
+
var ESLintReactSettingsSchema = object({
|
|
425
|
+
/**
|
|
426
|
+
* The source where React is imported from.
|
|
427
|
+
* @description This allows to specify a custom import location for React when not using the official distribution.
|
|
428
|
+
* @default `"react"`
|
|
429
|
+
* @example `"@pika/react"`
|
|
430
|
+
*/
|
|
431
|
+
importSource: optional(string()),
|
|
432
|
+
/**
|
|
433
|
+
* The identifier that’s used for JSX Element creation.
|
|
434
|
+
* @default `"createElement"`
|
|
435
|
+
* @deprecated
|
|
436
|
+
*/
|
|
437
|
+
jsxPragma: optional(string()),
|
|
438
|
+
/**
|
|
439
|
+
* The identifier that’s used for JSX fragment elements.
|
|
440
|
+
* @description This should not be a member expression (i.e. use "Fragment" instead of "React.Fragment").
|
|
441
|
+
* @default `"Fragment"`
|
|
442
|
+
* @deprecated
|
|
443
|
+
*/
|
|
444
|
+
jsxPragmaFrag: optional(string()),
|
|
445
|
+
/**
|
|
446
|
+
* The name of the prop that is used for polymorphic components.
|
|
447
|
+
* @description This is used to determine the type of the component.
|
|
448
|
+
* @example `"as"`
|
|
449
|
+
*/
|
|
450
|
+
polymorphicPropName: optional(string()),
|
|
451
|
+
/**
|
|
452
|
+
* @internal
|
|
453
|
+
*/
|
|
454
|
+
strict: optional(boolean(), false),
|
|
455
|
+
/**
|
|
456
|
+
* Check both the shape and the import to determine if an API is from React.
|
|
457
|
+
* @description This can prevent false positives when using a irrelevant third-party library that has similar APIs to React.
|
|
458
|
+
* @default `true`
|
|
459
|
+
*/
|
|
460
|
+
skipImportCheck: optional(boolean(), true),
|
|
461
|
+
/**
|
|
462
|
+
* React version to use, "detect" means auto detect React version from the project’s dependencies.
|
|
463
|
+
* If `importSource` is specified, an equivalent version of React should be provided here.
|
|
464
|
+
* @example `"18.3.1"`
|
|
465
|
+
* @default `"detect"`
|
|
466
|
+
*/
|
|
467
|
+
version: optional(string()),
|
|
468
|
+
/**
|
|
469
|
+
* A object to define additional hooks that are equivalent to the built-in React Hooks.
|
|
470
|
+
* @description ESLint React will recognize these aliases as equivalent to the built-in hooks in all its rules.
|
|
471
|
+
* @example `{ useEffect: ["useIsomorphicLayoutEffect"] }`
|
|
472
|
+
*/
|
|
473
|
+
additionalHooks: optional(CustomHooksSchema),
|
|
474
|
+
/**
|
|
475
|
+
* An array of user-defined components
|
|
476
|
+
* @description This is used to inform the ESLint React plugins how to treat these components during checks.
|
|
477
|
+
* @example `[{ name: "Link", as: "a", attributes: [{ name: "to", as: "href" }, { name: "rel", defaultValue: "noopener noreferrer" }] }]`
|
|
478
|
+
*/
|
|
479
|
+
additionalComponents: optional(array(CustomComponentSchema))
|
|
480
|
+
});
|
|
481
|
+
var DEFAULT_ESLINT_REACT_SETTINGS = {
|
|
482
|
+
...parse(ESLintReactSettingsSchema, {}),
|
|
483
|
+
importSource: "react"};
|
|
22
484
|
function getRequireExpressionArguments(node) {
|
|
23
485
|
return match(node).with({ type: AST_NODE_TYPES.CallExpression, arguments: P.select(), callee: { type: AST_NODE_TYPES.Identifier, name: "require" } }, identity).with({ type: AST_NODE_TYPES.MemberExpression, object: P.select() }, getRequireExpressionArguments).otherwise(() => _);
|
|
24
486
|
}
|
|
25
|
-
function isInitializedFromReact(name,
|
|
487
|
+
function isInitializedFromReact(name, importSource, initialScope) {
|
|
26
488
|
if (name.toLowerCase() === "react") return true;
|
|
27
489
|
const latestDef = VAR.findVariable(name, initialScope)?.defs.at(-1);
|
|
28
490
|
if (latestDef == null) return false;
|
|
@@ -30,81 +492,101 @@ function isInitializedFromReact(name, source, initialScope) {
|
|
|
30
492
|
if (node.type === AST_NODE_TYPES.VariableDeclarator && node.init != null) {
|
|
31
493
|
const { init } = node;
|
|
32
494
|
if (init.type === AST_NODE_TYPES.MemberExpression && init.object.type === AST_NODE_TYPES.Identifier) {
|
|
33
|
-
return isInitializedFromReact(init.object.name,
|
|
495
|
+
return isInitializedFromReact(init.object.name, importSource, initialScope);
|
|
34
496
|
}
|
|
35
497
|
if (init.type === AST_NODE_TYPES.Identifier) {
|
|
36
|
-
return isInitializedFromReact(init.name,
|
|
498
|
+
return isInitializedFromReact(init.name, importSource, initialScope);
|
|
37
499
|
}
|
|
38
500
|
const args = getRequireExpressionArguments(init);
|
|
39
501
|
const arg0 = args?.[0];
|
|
40
|
-
if (arg0 == null || !
|
|
502
|
+
if (arg0 == null || !AST8.isKindOfLiteral(arg0, "string")) {
|
|
41
503
|
return false;
|
|
42
504
|
}
|
|
43
|
-
return arg0.value ===
|
|
505
|
+
return arg0.value === importSource || arg0.value.startsWith(`${importSource}/`);
|
|
44
506
|
}
|
|
45
|
-
return parent?.type === AST_NODE_TYPES.ImportDeclaration && parent.source.value ===
|
|
507
|
+
return parent?.type === AST_NODE_TYPES.ImportDeclaration && parent.source.value === importSource;
|
|
46
508
|
}
|
|
47
509
|
|
|
48
510
|
// src/utils/is-from-react.ts
|
|
511
|
+
var defaultImportSource = DEFAULT_ESLINT_REACT_SETTINGS$1.importSource;
|
|
512
|
+
function isFromReactLoose(node, name) {
|
|
513
|
+
if (node.type === AST_NODE_TYPES.MemberExpression) {
|
|
514
|
+
return node.object.type === AST_NODE_TYPES.Identifier && node.property.type === AST_NODE_TYPES.Identifier && node.property.name === name;
|
|
515
|
+
}
|
|
516
|
+
return node.name === name;
|
|
517
|
+
}
|
|
518
|
+
function isFromReactStrict(node, name, importSource, initialScope) {
|
|
519
|
+
if (node.type === AST_NODE_TYPES.MemberExpression) {
|
|
520
|
+
return node.object.type === AST_NODE_TYPES.Identifier && node.property.type === AST_NODE_TYPES.Identifier && node.property.name === name && isInitializedFromReact(node.object.name, importSource, initialScope);
|
|
521
|
+
}
|
|
522
|
+
if (node.name === name) {
|
|
523
|
+
return isInitializedFromReact(name, importSource, initialScope);
|
|
524
|
+
}
|
|
525
|
+
return false;
|
|
526
|
+
}
|
|
49
527
|
function isFromReact(name) {
|
|
50
|
-
return (
|
|
51
|
-
const
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
return node.object.type === AST_NODE_TYPES.Identifier && node.property.type === AST_NODE_TYPES.Identifier && node.property.name === name;
|
|
55
|
-
}
|
|
56
|
-
return node.name === name;
|
|
57
|
-
}
|
|
58
|
-
const importSource = settings.importSource ?? DEFAULT_ESLINT_REACT_SETTINGS.importSource;
|
|
59
|
-
const initialScope = context.sourceCode.getScope(node);
|
|
60
|
-
if (node.type === AST_NODE_TYPES.MemberExpression) {
|
|
61
|
-
return node.object.type === AST_NODE_TYPES.Identifier && node.property.type === AST_NODE_TYPES.Identifier && node.property.name === name && isInitializedFromReact(node.object.name, importSource, initialScope);
|
|
62
|
-
}
|
|
63
|
-
if (node.name === name) {
|
|
64
|
-
return isInitializedFromReact(name, importSource, initialScope);
|
|
65
|
-
}
|
|
66
|
-
return false;
|
|
528
|
+
return (context, node) => {
|
|
529
|
+
const { importSource = defaultImportSource, skipImportCheck = true } = unsafeDecodeSettings(context.settings);
|
|
530
|
+
if (skipImportCheck) return isFromReactLoose(node, name);
|
|
531
|
+
return isFromReactStrict(node, name, importSource, context.sourceCode.getScope(node));
|
|
67
532
|
};
|
|
68
533
|
}
|
|
69
|
-
function
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const initialScope = context.sourceCode.getScope(node);
|
|
82
|
-
if (node.property.type !== AST_NODE_TYPES.Identifier || node.property.name !== name) {
|
|
83
|
-
return false;
|
|
84
|
-
}
|
|
85
|
-
if (node.object.type === AST_NODE_TYPES.Identifier && node.object.name === memberName) {
|
|
86
|
-
return isInitializedFromReact(node.object.name, importSource, initialScope);
|
|
87
|
-
}
|
|
88
|
-
if (node.object.type === AST_NODE_TYPES.MemberExpression && node.object.object.type === AST_NODE_TYPES.Identifier && isInitializedFromReact(node.object.object.name, importSource, initialScope) && node.object.property.type === AST_NODE_TYPES.Identifier) {
|
|
89
|
-
return node.object.property.name === memberName;
|
|
90
|
-
}
|
|
534
|
+
function isFromReactMemberLoose(node, memberName, name) {
|
|
535
|
+
const { object: object2, property } = node;
|
|
536
|
+
if (property.type !== AST_NODE_TYPES.Identifier || property.name !== name) return false;
|
|
537
|
+
if (object2.type === AST_NODE_TYPES.Identifier && object2.name === memberName) return true;
|
|
538
|
+
if (object2.type === AST_NODE_TYPES.MemberExpression && object2.object.type === AST_NODE_TYPES.Identifier && object2.property.type === AST_NODE_TYPES.Identifier) {
|
|
539
|
+
return object2.property.name === memberName;
|
|
540
|
+
}
|
|
541
|
+
return false;
|
|
542
|
+
}
|
|
543
|
+
function isFromReactMemberStrict(node, memberName, name, importSource, initialScope) {
|
|
544
|
+
const { object: object2, property } = node;
|
|
545
|
+
if (property.type !== AST_NODE_TYPES.Identifier || property.name !== name) {
|
|
91
546
|
return false;
|
|
547
|
+
}
|
|
548
|
+
if (object2.type === AST_NODE_TYPES.Identifier && object2.name === memberName) {
|
|
549
|
+
return isInitializedFromReact(object2.name, importSource, initialScope);
|
|
550
|
+
}
|
|
551
|
+
if (object2.type === AST_NODE_TYPES.MemberExpression && object2.object.type === AST_NODE_TYPES.Identifier && isInitializedFromReact(object2.object.name, importSource, initialScope) && object2.property.type === AST_NODE_TYPES.Identifier) {
|
|
552
|
+
return object2.property.name === memberName;
|
|
553
|
+
}
|
|
554
|
+
return false;
|
|
555
|
+
}
|
|
556
|
+
function isFromReactMember(memberName, name) {
|
|
557
|
+
return (context, node) => {
|
|
558
|
+
const { importSource = defaultImportSource, skipImportCheck = true } = unsafeDecodeSettings(context.settings);
|
|
559
|
+
if (skipImportCheck) return isFromReactMemberLoose(node, memberName, name);
|
|
560
|
+
return isFromReactMemberStrict(node, memberName, name, importSource, context.sourceCode.getScope(node));
|
|
92
561
|
};
|
|
93
562
|
}
|
|
563
|
+
|
|
564
|
+
// src/utils/is-call-from-react.ts
|
|
94
565
|
function isCallFromReact(name) {
|
|
95
|
-
return dual(2, (
|
|
566
|
+
return dual(2, (context, node) => {
|
|
96
567
|
if (node.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
97
|
-
if (!
|
|
98
|
-
return isFromReact(name)(node.callee
|
|
568
|
+
if (!AST8.isOneOf([AST_NODE_TYPES.Identifier, AST_NODE_TYPES.MemberExpression])(node.callee)) return false;
|
|
569
|
+
return isFromReact(name)(context, node.callee);
|
|
99
570
|
});
|
|
100
571
|
}
|
|
101
572
|
function isCallFromReactMember(pragmaMemberName, name) {
|
|
102
|
-
return dual(2, (
|
|
573
|
+
return dual(2, (context, node) => {
|
|
103
574
|
if (node.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
104
|
-
if (!
|
|
105
|
-
return isFromReactMember(pragmaMemberName, name)(node.callee
|
|
575
|
+
if (!AST8.is(AST_NODE_TYPES.MemberExpression)(node.callee)) return false;
|
|
576
|
+
return isFromReactMember(pragmaMemberName, name)(context, node.callee);
|
|
106
577
|
});
|
|
107
578
|
}
|
|
579
|
+
var DISPLAY_NAME_ASSIGNMENT_SELECTOR = [
|
|
580
|
+
"AssignmentExpression",
|
|
581
|
+
"[type]",
|
|
582
|
+
"[operator='=']",
|
|
583
|
+
"[left.type='MemberExpression']",
|
|
584
|
+
"[left.property.name='displayName']"
|
|
585
|
+
].join("");
|
|
586
|
+
function isDisplayNameAssignment(node) {
|
|
587
|
+
if (node == null) return false;
|
|
588
|
+
return node.type === AST_NODE_TYPES.AssignmentExpression && node.operator === "=" && node.left.type === AST_NODE_TYPES.MemberExpression && node.left.property.type === AST_NODE_TYPES.Identifier && node.left.property.name === "displayName";
|
|
589
|
+
}
|
|
108
590
|
|
|
109
591
|
// src/utils/is-react-api.ts
|
|
110
592
|
function isReactAPIWithName(name, member) {
|
|
@@ -136,21 +618,6 @@ var isCreateRefCall = isReactAPICallWithName("createRef");
|
|
|
136
618
|
var isForwardRefCall = isReactAPICallWithName("forwardRef");
|
|
137
619
|
var isMemoCall = isReactAPICallWithName("memo");
|
|
138
620
|
|
|
139
|
-
// src/element/hierarchy.ts
|
|
140
|
-
function isInsideCreateElementProps(node, context) {
|
|
141
|
-
const call = AST9.findParentNode(node, isCreateElementCall(context));
|
|
142
|
-
if (call == null) return false;
|
|
143
|
-
const prop = AST9.findParentNode(node, AST9.is(AST_NODE_TYPES.ObjectExpression));
|
|
144
|
-
if (prop == null) return false;
|
|
145
|
-
return prop === call.arguments[1];
|
|
146
|
-
}
|
|
147
|
-
function isChildrenOfCreateElement(node, context) {
|
|
148
|
-
const parent = node.parent;
|
|
149
|
-
if (parent == null || parent.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
150
|
-
if (!isCreateElementCall(parent, context)) return false;
|
|
151
|
-
return parent.arguments.slice(2).some((arg) => arg === node);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
621
|
// src/hook/hook-name.ts
|
|
155
622
|
var RE_HOOK_NAME = /^use[A-Z\d]/u;
|
|
156
623
|
function isReactHookName(name) {
|
|
@@ -160,7 +627,7 @@ function isReactHookName(name) {
|
|
|
160
627
|
// src/hook/is.ts
|
|
161
628
|
function isReactHook(node) {
|
|
162
629
|
if (node == null) return _;
|
|
163
|
-
const id =
|
|
630
|
+
const id = AST8.getFunctionIdentifier(node);
|
|
164
631
|
return id?.name != null && isReactHookName(id.name);
|
|
165
632
|
}
|
|
166
633
|
function isReactHookCall(node) {
|
|
@@ -176,17 +643,19 @@ function isReactHookCall(node) {
|
|
|
176
643
|
}
|
|
177
644
|
return false;
|
|
178
645
|
}
|
|
179
|
-
function isReactHookCallWithName(
|
|
646
|
+
function isReactHookCallWithName(context, node) {
|
|
180
647
|
if (node == null) return constFalse;
|
|
181
|
-
const
|
|
182
|
-
|
|
648
|
+
const {
|
|
649
|
+
importSource = DEFAULT_ESLINT_REACT_SETTINGS.importSource,
|
|
650
|
+
skipImportCheck = true
|
|
651
|
+
} = unsafeDecodeSettings(context.settings);
|
|
183
652
|
const initialScope = context.sourceCode.getScope(node);
|
|
184
653
|
return (name) => {
|
|
185
654
|
switch (true) {
|
|
186
655
|
case (node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === name):
|
|
187
|
-
return
|
|
656
|
+
return skipImportCheck || isInitializedFromReact(name, importSource, initialScope);
|
|
188
657
|
case (node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === name && "name" in node.callee.object):
|
|
189
|
-
return
|
|
658
|
+
return skipImportCheck || isInitializedFromReact(node.callee.object.name, importSource, initialScope);
|
|
190
659
|
default:
|
|
191
660
|
return false;
|
|
192
661
|
}
|
|
@@ -205,16 +674,18 @@ function isReactHookCallWithNameLoose(node) {
|
|
|
205
674
|
}
|
|
206
675
|
};
|
|
207
676
|
}
|
|
208
|
-
function isReactHookCallWithNameAlias(
|
|
209
|
-
const
|
|
210
|
-
|
|
677
|
+
function isReactHookCallWithNameAlias(context, name, alias) {
|
|
678
|
+
const {
|
|
679
|
+
importSource = DEFAULT_ESLINT_REACT_SETTINGS.importSource,
|
|
680
|
+
skipImportCheck = true
|
|
681
|
+
} = unsafeDecodeSettings(context.settings);
|
|
211
682
|
return (node) => {
|
|
212
683
|
const initialScope = context.sourceCode.getScope(node);
|
|
213
684
|
switch (true) {
|
|
214
685
|
case (node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === name):
|
|
215
|
-
return
|
|
686
|
+
return skipImportCheck || isInitializedFromReact(name, importSource, initialScope);
|
|
216
687
|
case (node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === name && "name" in node.callee.object):
|
|
217
|
-
return
|
|
688
|
+
return skipImportCheck || isInitializedFromReact(node.callee.object.name, importSource, initialScope);
|
|
218
689
|
default:
|
|
219
690
|
return alias.some(isReactHookCallWithNameLoose(node));
|
|
220
691
|
}
|
|
@@ -252,13 +723,13 @@ var isUseTransitionCall = flip(isReactHookCallWithName)("useTransition");
|
|
|
252
723
|
|
|
253
724
|
// src/hook/hierarchy.ts
|
|
254
725
|
function isInsideReactHook(node) {
|
|
255
|
-
return isReactHook(
|
|
726
|
+
return isReactHook(AST8.findParentNode(node, AST8.isFunction));
|
|
256
727
|
}
|
|
257
728
|
function useHookCollector() {
|
|
258
729
|
const hooks = /* @__PURE__ */ new Map();
|
|
259
730
|
const functionEntries = [];
|
|
260
731
|
const onFunctionEnter = (node) => {
|
|
261
|
-
const id =
|
|
732
|
+
const id = AST8.getFunctionIdentifier(node);
|
|
262
733
|
const key = getId();
|
|
263
734
|
const name = id?.name;
|
|
264
735
|
if (name != null && isReactHookName(name)) {
|
|
@@ -347,26 +818,53 @@ var ERComponentFlag = {
|
|
|
347
818
|
ForwardRef: 1n << 3n,
|
|
348
819
|
Async: 1n << 4n
|
|
349
820
|
};
|
|
350
|
-
function isComponentWrapperCall(
|
|
821
|
+
function isComponentWrapperCall(context, node) {
|
|
351
822
|
if (node.type !== AST_NODE_TYPES.CallExpression) {
|
|
352
823
|
return false;
|
|
353
824
|
}
|
|
354
|
-
return isMemoCall(
|
|
825
|
+
return isMemoCall(context, node) || isForwardRefCall(context, node) || isReactHookCallWithNameLoose(node)("useCallback");
|
|
355
826
|
}
|
|
356
|
-
function getFunctionComponentIdentifier(
|
|
357
|
-
const functionId =
|
|
827
|
+
function getFunctionComponentIdentifier(context, node) {
|
|
828
|
+
const functionId = AST8.getFunctionIdentifier(node);
|
|
358
829
|
if (functionId != null) {
|
|
359
830
|
return functionId;
|
|
360
831
|
}
|
|
361
832
|
const { parent } = node;
|
|
362
|
-
if (parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCall(
|
|
833
|
+
if (parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCall(context, parent) && parent.parent.type === AST_NODE_TYPES.VariableDeclarator && parent.parent.id.type === AST_NODE_TYPES.Identifier) {
|
|
363
834
|
return parent.parent.id;
|
|
364
835
|
}
|
|
365
|
-
if (parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCall(
|
|
836
|
+
if (parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCall(context, parent) && parent.parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCall(context, parent.parent) && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator && parent.parent.parent.id.type === AST_NODE_TYPES.Identifier) {
|
|
366
837
|
return parent.parent.parent.id;
|
|
367
838
|
}
|
|
368
839
|
return _;
|
|
369
840
|
}
|
|
841
|
+
var RE_COMPONENT_NAME = /^_?[A-Z]/u;
|
|
842
|
+
function getComponentNameFromIdentifier(node) {
|
|
843
|
+
if (node == null) return _;
|
|
844
|
+
return Array.isArray(node) ? node.map((n) => n.name).join(".") : node.name;
|
|
845
|
+
}
|
|
846
|
+
function isComponentName(name) {
|
|
847
|
+
return RE_COMPONENT_NAME.test(name);
|
|
848
|
+
}
|
|
849
|
+
function hasNoneOrValidComponentName(context, node) {
|
|
850
|
+
const id = getFunctionComponentIdentifier(context, node);
|
|
851
|
+
if (id == null) return true;
|
|
852
|
+
const name = Array.isArray(id) ? id.at(-1)?.name : id.name;
|
|
853
|
+
return name != null && isComponentName(name);
|
|
854
|
+
}
|
|
855
|
+
function isInsideCreateElementProps(context, node) {
|
|
856
|
+
const call = AST8.findParentNode(node, isCreateElementCall(context));
|
|
857
|
+
if (call == null) return false;
|
|
858
|
+
const prop = AST8.findParentNode(node, AST8.is(AST_NODE_TYPES.ObjectExpression));
|
|
859
|
+
if (prop == null) return false;
|
|
860
|
+
return prop === call.arguments[1];
|
|
861
|
+
}
|
|
862
|
+
function isChildrenOfCreateElement(context, node) {
|
|
863
|
+
const parent = node.parent;
|
|
864
|
+
if (parent == null || parent.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
865
|
+
if (!isCreateElementCall(context, parent)) return false;
|
|
866
|
+
return parent.arguments.slice(2).some((arg) => arg === node);
|
|
867
|
+
}
|
|
370
868
|
function isClassComponent(node) {
|
|
371
869
|
if ("superClass" in node && node.superClass != null) {
|
|
372
870
|
const re = /^(?:Pure)?Component$/u;
|
|
@@ -394,28 +892,28 @@ function isPureComponent(node) {
|
|
|
394
892
|
|
|
395
893
|
// src/component/component-lifecycle.ts
|
|
396
894
|
function isComponentDidMount(node) {
|
|
397
|
-
return
|
|
895
|
+
return AST8.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidMount";
|
|
398
896
|
}
|
|
399
897
|
function isComponentWillUnmount(node) {
|
|
400
|
-
return
|
|
898
|
+
return AST8.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillUnmount";
|
|
401
899
|
}
|
|
402
900
|
function isComponentDidCatch(node) {
|
|
403
|
-
return
|
|
901
|
+
return AST8.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidCatch";
|
|
404
902
|
}
|
|
405
903
|
function isGetDerivedStateFromError(node) {
|
|
406
|
-
return
|
|
904
|
+
return AST8.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromError";
|
|
407
905
|
}
|
|
408
906
|
function isGetDerivedStateFromProps(node) {
|
|
409
|
-
return
|
|
907
|
+
return AST8.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromProps";
|
|
410
908
|
}
|
|
411
909
|
function isFunctionOfComponentDidMount(node) {
|
|
412
|
-
return
|
|
910
|
+
return AST8.isFunction(node) && isComponentDidMount(node.parent) && node.parent.value === node;
|
|
413
911
|
}
|
|
414
912
|
function isFunctionOfComponentWillUnmount(node) {
|
|
415
|
-
return
|
|
913
|
+
return AST8.isFunction(node) && isComponentWillUnmount(node.parent) && node.parent.value === node;
|
|
416
914
|
}
|
|
417
915
|
function isRenderMethodLike(node) {
|
|
418
|
-
return
|
|
916
|
+
return AST8.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "render" && node.parent.parent.type === AST_NODE_TYPES.ClassDeclaration;
|
|
419
917
|
}
|
|
420
918
|
function isFunctionOfRenderMethod(node) {
|
|
421
919
|
if (!isRenderMethodLike(node.parent)) {
|
|
@@ -424,21 +922,46 @@ function isFunctionOfRenderMethod(node) {
|
|
|
424
922
|
return isClassComponent(node.parent.parent.parent);
|
|
425
923
|
}
|
|
426
924
|
function isInsideRenderMethod(node) {
|
|
427
|
-
return
|
|
925
|
+
return AST8.findParentNode(node, (node2) => isRenderMethodLike(node2) && isClassComponent(node2.parent.parent)) != null;
|
|
428
926
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
927
|
+
|
|
928
|
+
// src/component/hierarchy.ts
|
|
929
|
+
function hasValidHierarchy(context, node, hint) {
|
|
930
|
+
if (isChildrenOfCreateElement(context, node) || isFunctionOfRenderMethod(node)) {
|
|
931
|
+
return false;
|
|
932
|
+
}
|
|
933
|
+
if (hint & ERComponentHint.SkipMapCallback && AST8.isMapCallLoose(node.parent)) {
|
|
934
|
+
return false;
|
|
935
|
+
}
|
|
936
|
+
if (hint & ERComponentHint.SkipObjectMethod && isFunctionOfObjectMethod(node.parent)) {
|
|
937
|
+
return false;
|
|
938
|
+
}
|
|
939
|
+
if (hint & ERComponentHint.SkipClassMethod && isFunctionOfClassMethod(node.parent)) {
|
|
940
|
+
return false;
|
|
941
|
+
}
|
|
942
|
+
if (hint & ERComponentHint.SkipClassProperty && isFunctionOfClassProperty(node.parent)) {
|
|
943
|
+
return false;
|
|
944
|
+
}
|
|
945
|
+
const boundaryNode = AST8.findParentNode(
|
|
946
|
+
node,
|
|
947
|
+
AST8.isOneOf([
|
|
948
|
+
AST_NODE_TYPES.JSXExpressionContainer,
|
|
949
|
+
AST_NODE_TYPES.ArrowFunctionExpression,
|
|
950
|
+
AST_NODE_TYPES.FunctionExpression,
|
|
951
|
+
AST_NODE_TYPES.Property,
|
|
952
|
+
AST_NODE_TYPES.ClassBody
|
|
953
|
+
])
|
|
954
|
+
);
|
|
955
|
+
return boundaryNode == null || boundaryNode.type !== AST_NODE_TYPES.JSXExpressionContainer;
|
|
433
956
|
}
|
|
434
|
-
function
|
|
435
|
-
return
|
|
957
|
+
function isFunctionOfClassMethod(node) {
|
|
958
|
+
return (node.type === AST_NODE_TYPES.FunctionExpression || node.type === AST_NODE_TYPES.ArrowFunctionExpression) && node.parent.type === AST_NODE_TYPES.MethodDefinition;
|
|
436
959
|
}
|
|
437
|
-
function
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
return
|
|
960
|
+
function isFunctionOfClassProperty(node) {
|
|
961
|
+
return (node.type === AST_NODE_TYPES.FunctionExpression || node.type === AST_NODE_TYPES.ArrowFunctionExpression) && node.parent.type === AST_NODE_TYPES.Property;
|
|
962
|
+
}
|
|
963
|
+
function isFunctionOfObjectMethod(node) {
|
|
964
|
+
return (node.type === AST_NODE_TYPES.FunctionExpression || node.type === AST_NODE_TYPES.ArrowFunctionExpression) && node.parent.type === AST_NODE_TYPES.Property && node.parent.parent.type === AST_NODE_TYPES.ObjectExpression;
|
|
442
965
|
}
|
|
443
966
|
|
|
444
967
|
// src/component/component-collector.ts
|
|
@@ -456,7 +979,7 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
|
|
|
456
979
|
const entry = functionEntries.at(-1);
|
|
457
980
|
if (entry == null) return;
|
|
458
981
|
if (!entry.isComponent) return functionEntries.pop();
|
|
459
|
-
const shouldDrop =
|
|
982
|
+
const shouldDrop = AST8.getNestedReturnStatements(entry.node.body).slice().reverse().some((r) => {
|
|
460
983
|
return context.sourceCode.getScope(r).block === entry.node && r.argument != null && !JSX3.isJSXValue(r.argument, jsxCtx, hint);
|
|
461
984
|
});
|
|
462
985
|
if (shouldDrop) {
|
|
@@ -481,10 +1004,10 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
|
|
|
481
1004
|
const entry = getCurrentEntry();
|
|
482
1005
|
if (entry == null) return;
|
|
483
1006
|
const { body } = entry.node;
|
|
484
|
-
const isComponent = hasNoneOrValidComponentName(entry.node
|
|
1007
|
+
const isComponent = hasNoneOrValidComponentName(context, entry.node) && JSX3.isJSXValue(body, jsxCtx, hint) && hasValidHierarchy(context, entry.node, hint);
|
|
485
1008
|
if (!isComponent) return;
|
|
486
|
-
const initPath =
|
|
487
|
-
const id = getFunctionComponentIdentifier(entry.node
|
|
1009
|
+
const initPath = AST8.getFunctionInitPath(entry.node);
|
|
1010
|
+
const id = getFunctionComponentIdentifier(context, entry.node);
|
|
488
1011
|
const name = getComponentNameFromIdentifier(id);
|
|
489
1012
|
const key = getId();
|
|
490
1013
|
components.set(key, {
|
|
@@ -521,11 +1044,11 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
|
|
|
521
1044
|
"ReturnStatement[type]"(node) {
|
|
522
1045
|
const entry = getCurrentEntry();
|
|
523
1046
|
if (entry == null) return;
|
|
524
|
-
const isComponent = hasNoneOrValidComponentName(entry.node
|
|
1047
|
+
const isComponent = hasNoneOrValidComponentName(context, entry.node) && JSX3.isJSXValue(node.argument, jsxCtx, hint) && hasValidHierarchy(context, entry.node, hint);
|
|
525
1048
|
if (!isComponent) return;
|
|
526
1049
|
entry.isComponent = true;
|
|
527
|
-
const initPath =
|
|
528
|
-
const id = getFunctionComponentIdentifier(entry.node
|
|
1050
|
+
const initPath = AST8.getFunctionInitPath(entry.node);
|
|
1051
|
+
const id = getFunctionComponentIdentifier(context, entry.node);
|
|
529
1052
|
const name = getComponentNameFromIdentifier(id);
|
|
530
1053
|
components.set(entry.key, {
|
|
531
1054
|
id,
|
|
@@ -543,40 +1066,12 @@ function useComponentCollector(context, hint = DEFAULT_COMPONENT_HINT, options =
|
|
|
543
1066
|
};
|
|
544
1067
|
return { ctx, listeners };
|
|
545
1068
|
}
|
|
546
|
-
function hasValidHierarchy(node, context, hint) {
|
|
547
|
-
if (isChildrenOfCreateElement(node, context) || isFunctionOfRenderMethod(node)) {
|
|
548
|
-
return false;
|
|
549
|
-
}
|
|
550
|
-
if (hint & ERComponentHint.SkipMapCallback && AST9.isMapCallLoose(node.parent)) {
|
|
551
|
-
return false;
|
|
552
|
-
}
|
|
553
|
-
if (hint & ERComponentHint.SkipObjectMethod && AST9.isFunctionOfObjectMethod(node.parent)) {
|
|
554
|
-
return false;
|
|
555
|
-
}
|
|
556
|
-
if (hint & ERComponentHint.SkipClassMethod && AST9.isFunctionOfClassMethod(node.parent)) {
|
|
557
|
-
return false;
|
|
558
|
-
}
|
|
559
|
-
if (hint & ERComponentHint.SkipClassProperty && AST9.isFunctionOfClassProperty(node.parent)) {
|
|
560
|
-
return false;
|
|
561
|
-
}
|
|
562
|
-
const boundaryNode = AST9.findParentNode(
|
|
563
|
-
node,
|
|
564
|
-
AST9.isOneOf([
|
|
565
|
-
AST_NODE_TYPES.JSXExpressionContainer,
|
|
566
|
-
AST_NODE_TYPES.ArrowFunctionExpression,
|
|
567
|
-
AST_NODE_TYPES.FunctionExpression,
|
|
568
|
-
AST_NODE_TYPES.Property,
|
|
569
|
-
AST_NODE_TYPES.ClassBody
|
|
570
|
-
])
|
|
571
|
-
);
|
|
572
|
-
return boundaryNode == null || boundaryNode.type !== AST_NODE_TYPES.JSXExpressionContainer;
|
|
573
|
-
}
|
|
574
1069
|
function getComponentFlag(initPath) {
|
|
575
1070
|
let flag = ERComponentFlag.None;
|
|
576
|
-
if (initPath != null &&
|
|
1071
|
+
if (initPath != null && AST8.hasCallInFunctionInitPath("memo", initPath)) {
|
|
577
1072
|
flag |= ERComponentFlag.Memo;
|
|
578
1073
|
}
|
|
579
|
-
if (initPath != null &&
|
|
1074
|
+
if (initPath != null && AST8.hasCallInFunctionInitPath("forwardRef", initPath)) {
|
|
580
1075
|
flag |= ERComponentFlag.ForwardRef;
|
|
581
1076
|
}
|
|
582
1077
|
return flag;
|
|
@@ -593,7 +1088,7 @@ function useComponentCollectorLegacy() {
|
|
|
593
1088
|
if (!isClassComponent(node)) {
|
|
594
1089
|
return;
|
|
595
1090
|
}
|
|
596
|
-
const id =
|
|
1091
|
+
const id = AST8.getClassIdentifier(node);
|
|
597
1092
|
const key = getId();
|
|
598
1093
|
const flag = isPureComponent(node) ? ERComponentFlag.PureComponent : ERComponentFlag.None;
|
|
599
1094
|
components.set(
|
|
@@ -624,9 +1119,9 @@ var ERPhaseRelevance = birecord({
|
|
|
624
1119
|
setup: "cleanup"
|
|
625
1120
|
});
|
|
626
1121
|
var isInversePhase = dual(2, (a, b) => ERPhaseRelevance.get(a) === b);
|
|
627
|
-
function isRenderFunctionLoose(
|
|
1122
|
+
function isRenderFunctionLoose(context, node) {
|
|
628
1123
|
const { body, parent } = node;
|
|
629
|
-
if (
|
|
1124
|
+
if (AST8.getFunctionIdentifier(node)?.name.startsWith("render")) {
|
|
630
1125
|
return parent.type === AST_NODE_TYPES.JSXExpressionContainer && parent.parent.type === AST_NODE_TYPES.JSXAttribute && parent.parent.name.type === AST_NODE_TYPES.JSXIdentifier && parent.parent.name.name.startsWith("render");
|
|
631
1126
|
}
|
|
632
1127
|
return JSX3.isJSXValue(
|
|
@@ -637,11 +1132,11 @@ function isRenderFunctionLoose(node, context) {
|
|
|
637
1132
|
JSX3.JSXValueHint.SkipNullLiteral | JSX3.JSXValueHint.SkipUndefined | JSX3.JSXValueHint.StrictLogical | JSX3.JSXValueHint.StrictConditional
|
|
638
1133
|
);
|
|
639
1134
|
}
|
|
640
|
-
function isRenderPropLoose(
|
|
1135
|
+
function isRenderPropLoose(context, node) {
|
|
641
1136
|
if (node.name.type !== AST_NODE_TYPES.JSXIdentifier) {
|
|
642
1137
|
return false;
|
|
643
1138
|
}
|
|
644
|
-
return node.name.name.startsWith("render") && node.value?.type === AST_NODE_TYPES.JSXExpressionContainer &&
|
|
1139
|
+
return node.name.name.startsWith("render") && node.value?.type === AST_NODE_TYPES.JSXExpressionContainer && AST8.isFunction(node.value.expression) && isRenderFunctionLoose(context, node.value.expression);
|
|
645
1140
|
}
|
|
646
1141
|
function isDirectValueOfRenderPropertyLoose(node) {
|
|
647
1142
|
const matching = (node2) => {
|
|
@@ -653,7 +1148,7 @@ function isDeclaredInRenderPropLoose(node) {
|
|
|
653
1148
|
if (isDirectValueOfRenderPropertyLoose(node)) {
|
|
654
1149
|
return true;
|
|
655
1150
|
}
|
|
656
|
-
const parent =
|
|
1151
|
+
const parent = AST8.findParentNode(node, AST8.is(AST_NODE_TYPES.JSXExpressionContainer))?.parent;
|
|
657
1152
|
if (parent?.type !== AST_NODE_TYPES.JSXAttribute) {
|
|
658
1153
|
return false;
|
|
659
1154
|
}
|
|
@@ -661,17 +1156,17 @@ function isDeclaredInRenderPropLoose(node) {
|
|
|
661
1156
|
}
|
|
662
1157
|
function isThisSetState(node) {
|
|
663
1158
|
const { callee } = node;
|
|
664
|
-
return callee.type === AST_NODE_TYPES.MemberExpression &&
|
|
1159
|
+
return callee.type === AST_NODE_TYPES.MemberExpression && AST8.isThisExpression(callee.object) && callee.property.type === AST_NODE_TYPES.Identifier && callee.property.name === "setState";
|
|
665
1160
|
}
|
|
666
1161
|
function isFunctionOfUseEffectSetup(node) {
|
|
667
1162
|
if (node == null) return _;
|
|
668
1163
|
return node.parent?.type === AST_NODE_TYPES.CallExpression && node.parent.callee !== node && node.parent.callee.type === AST_NODE_TYPES.Identifier && node.parent.arguments.at(0) === node && isUseEffectCallLoose(node.parent);
|
|
669
1164
|
}
|
|
670
1165
|
function isFunctionOfUseEffectCleanup(node) {
|
|
671
|
-
const nearReturn =
|
|
672
|
-
const nearFunction =
|
|
673
|
-
const nearFunctionOfReturn =
|
|
1166
|
+
const nearReturn = AST8.findParentNode(node, AST8.is(AST_NODE_TYPES.ReturnStatement));
|
|
1167
|
+
const nearFunction = AST8.findParentNode(node, AST8.isFunction);
|
|
1168
|
+
const nearFunctionOfReturn = AST8.findParentNode(nearReturn, AST8.isFunction);
|
|
674
1169
|
return nearFunction === nearFunctionOfReturn && isFunctionOfUseEffectSetup(nearFunction);
|
|
675
1170
|
}
|
|
676
1171
|
|
|
677
|
-
export { DEFAULT_COMPONENT_HINT, DISPLAY_NAME_ASSIGNMENT_SELECTOR, ERComponentFlag, ERComponentHint, ERPhaseRelevance, RE_COMPONENT_NAME, RE_HOOK_NAME, getComponentNameFromIdentifier, getFunctionComponentIdentifier, hasNoneOrValidComponentName, isCallFromReact, isCallFromReactMember, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, isComponentName, isComponentWillUnmount, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isDisplayNameAssignment, isForwardRef, isForwardRefCall, isFromReact, isFromReactMember, isFunctionOfComponentDidMount, isFunctionOfComponentWillUnmount, isFunctionOfRenderMethod, isFunctionOfUseEffectCleanup, isFunctionOfUseEffectSetup, isGetDerivedStateFromError, isGetDerivedStateFromProps, isInitializedFromReact, isInsideCreateElementProps, isInsideReactHook, isInsideRenderMethod, isInversePhase, isMemo, isMemoCall, isPureComponent, isReactAPICallWithName, isReactAPIWithName, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookName, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isThisSetState, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCallLoose, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
|
|
1172
|
+
export { DEFAULT_COMPONENT_HINT, DISPLAY_NAME_ASSIGNMENT_SELECTOR, ERComponentFlag, ERComponentHint, ERPhaseRelevance, RE_COMPONENT_NAME, RE_HOOK_NAME, getComponentNameFromIdentifier, getFunctionComponentIdentifier, hasNoneOrValidComponentName, hasValidHierarchy, isCallFromReact, isCallFromReactMember, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, isComponentName, isComponentWillUnmount, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isDisplayNameAssignment, isForwardRef, isForwardRefCall, isFromReact, isFromReactLoose, isFromReactMember, isFromReactMemberLoose, isFromReactMemberStrict, isFromReactStrict, isFunctionOfComponentDidMount, isFunctionOfComponentWillUnmount, isFunctionOfRenderMethod, isFunctionOfUseEffectCleanup, isFunctionOfUseEffectSetup, isGetDerivedStateFromError, isGetDerivedStateFromProps, isInitializedFromReact, isInsideCreateElementProps, isInsideReactHook, isInsideRenderMethod, isInversePhase, isMemo, isMemoCall, isPureComponent, isReactAPICallWithName, isReactAPIWithName, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookName, isRenderFunctionLoose, isRenderMethodLike, isRenderPropLoose, isThisSetState, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCallLoose, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
|