@eslint-react/core 2.0.0-next.0 → 2.0.0-next.1
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 +195 -340
- package/package.json +9 -17
- package/dist/index.d.mts +0 -544
- package/dist/index.mjs +0 -927
package/dist/index.mjs
DELETED
|
@@ -1,927 +0,0 @@
|
|
|
1
|
-
import { AST_NODE_TYPES } from '@typescript-eslint/types';
|
|
2
|
-
import * as AST14 from '@eslint-react/ast';
|
|
3
|
-
import { flip, dual, constFalse, identity, constTrue, _ } from '@eslint-react/eff';
|
|
4
|
-
import { RegExp, Selector } from '@eslint-react/kit';
|
|
5
|
-
import { coerceSettings, DEFAULT_ESLINT_REACT_SETTINGS, getId } from '@eslint-react/shared';
|
|
6
|
-
import * as VAR3 from '@eslint-react/var';
|
|
7
|
-
import { isMatching, P, match } from 'ts-pattern';
|
|
8
|
-
import birecord from 'birecord';
|
|
9
|
-
|
|
10
|
-
// src/component/component-children.ts
|
|
11
|
-
function isReactAPI(api) {
|
|
12
|
-
const func = (context, node) => {
|
|
13
|
-
if (node == null) return false;
|
|
14
|
-
const getText = (n) => context.sourceCode.getText(n);
|
|
15
|
-
const name = AST14.toString(node, getText);
|
|
16
|
-
if (name === api) return true;
|
|
17
|
-
if (name.substring(name.indexOf(".") + 1) === api) return true;
|
|
18
|
-
return false;
|
|
19
|
-
};
|
|
20
|
-
return dual(2, func);
|
|
21
|
-
}
|
|
22
|
-
function isReactAPICall(api) {
|
|
23
|
-
const func = (context, node) => {
|
|
24
|
-
if (node == null) return false;
|
|
25
|
-
if (node.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
26
|
-
return isReactAPI(api)(context, node.callee);
|
|
27
|
-
};
|
|
28
|
-
return dual(2, func);
|
|
29
|
-
}
|
|
30
|
-
var isCaptureOwnerStack = isReactAPI("captureOwnerStack");
|
|
31
|
-
var isChildrenCount = isReactAPI("Children.count");
|
|
32
|
-
var isChildrenForEach = isReactAPI("Children.forEach");
|
|
33
|
-
var isChildrenMap = isReactAPI("Children.map");
|
|
34
|
-
var isChildrenOnly = isReactAPI("Children.only");
|
|
35
|
-
var isChildrenToArray = isReactAPI("Children.toArray");
|
|
36
|
-
var isCloneElement = isReactAPI("cloneElement");
|
|
37
|
-
var isCreateContext = isReactAPI("createContext");
|
|
38
|
-
var isCreateElement = isReactAPI("createElement");
|
|
39
|
-
var isCreateRef = isReactAPI("createRef");
|
|
40
|
-
var isForwardRef = isReactAPI("forwardRef");
|
|
41
|
-
var isMemo = isReactAPI("memo");
|
|
42
|
-
var isLazy = isReactAPI("lazy");
|
|
43
|
-
var isCaptureOwnerStackCall = isReactAPICall("captureOwnerStack");
|
|
44
|
-
var isChildrenCountCall = isReactAPICall("Children.count");
|
|
45
|
-
var isChildrenForEachCall = isReactAPICall("Children.forEach");
|
|
46
|
-
var isChildrenMapCall = isReactAPICall("Children.map");
|
|
47
|
-
var isChildrenOnlyCall = isReactAPICall("Children.only");
|
|
48
|
-
var isChildrenToArrayCall = isReactAPICall("Children.toArray");
|
|
49
|
-
var isCloneElementCall = isReactAPICall("cloneElement");
|
|
50
|
-
var isCreateContextCall = isReactAPICall("createContext");
|
|
51
|
-
var isCreateElementCall = isReactAPICall("createElement");
|
|
52
|
-
var isCreateRefCall = isReactAPICall("createRef");
|
|
53
|
-
var isForwardRefCall = isReactAPICall("forwardRef");
|
|
54
|
-
var isMemoCall = isReactAPICall("memo");
|
|
55
|
-
var isLazyCall = isReactAPICall("lazy");
|
|
56
|
-
|
|
57
|
-
// src/component/component-children.ts
|
|
58
|
-
function isChildrenOfCreateElement(context, node) {
|
|
59
|
-
const parent = node.parent;
|
|
60
|
-
if (parent == null || parent.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
61
|
-
if (!isCreateElementCall(context, parent)) return false;
|
|
62
|
-
return parent.arguments.slice(2).some((arg) => arg === node);
|
|
63
|
-
}
|
|
64
|
-
function getInstanceId(node, prev) {
|
|
65
|
-
switch (true) {
|
|
66
|
-
case (node.type === AST_NODE_TYPES.VariableDeclarator && node.init === prev):
|
|
67
|
-
return node.id;
|
|
68
|
-
case (node.type === AST_NODE_TYPES.AssignmentExpression && node.right === prev):
|
|
69
|
-
return node.left;
|
|
70
|
-
case (node.type === AST_NODE_TYPES.PropertyDefinition && node.value === prev):
|
|
71
|
-
return node.key;
|
|
72
|
-
case (node.type === AST_NODE_TYPES.BlockStatement || node.type === AST_NODE_TYPES.Program || node.parent === node):
|
|
73
|
-
return _;
|
|
74
|
-
default:
|
|
75
|
-
return getInstanceId(node.parent, node);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
function getRequireExpressionArguments(node) {
|
|
79
|
-
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(() => null);
|
|
80
|
-
}
|
|
81
|
-
function isInitializedFromReact(name, importSource, initialScope) {
|
|
82
|
-
if (name.toLowerCase() === "react") return true;
|
|
83
|
-
const latestDef = VAR3.findVariable(name, initialScope)?.defs.at(-1);
|
|
84
|
-
if (latestDef == null) return false;
|
|
85
|
-
const { node, parent } = latestDef;
|
|
86
|
-
if (node.type === AST_NODE_TYPES.VariableDeclarator && node.init != null) {
|
|
87
|
-
const { init } = node;
|
|
88
|
-
if (init.type === AST_NODE_TYPES.MemberExpression && init.object.type === AST_NODE_TYPES.Identifier) {
|
|
89
|
-
return isInitializedFromReact(init.object.name, importSource, initialScope);
|
|
90
|
-
}
|
|
91
|
-
if (init.type === AST_NODE_TYPES.Identifier) {
|
|
92
|
-
return isInitializedFromReact(init.name, importSource, initialScope);
|
|
93
|
-
}
|
|
94
|
-
const args = getRequireExpressionArguments(init);
|
|
95
|
-
const arg0 = args?.[0];
|
|
96
|
-
if (arg0 == null || !AST14.isLiteral(arg0, "string")) {
|
|
97
|
-
return false;
|
|
98
|
-
}
|
|
99
|
-
return arg0.value === importSource || arg0.value.startsWith(`${importSource}/`);
|
|
100
|
-
}
|
|
101
|
-
return parent?.type === AST_NODE_TYPES.ImportDeclaration && parent.source.value === importSource;
|
|
102
|
-
}
|
|
103
|
-
function isInstanceIdEqual(context, a, b) {
|
|
104
|
-
return AST14.isNodeEqual(a, b) || VAR3.isNodeValueEqual(a, b, [
|
|
105
|
-
context.sourceCode.getScope(a),
|
|
106
|
-
context.sourceCode.getScope(b)
|
|
107
|
-
]);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// src/hook/hook-name.ts
|
|
111
|
-
function isReactHookName(name) {
|
|
112
|
-
return name === "use" || /^use[A-Z0-9]/.test(name);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// src/hook/hook-is.ts
|
|
116
|
-
function isReactHook(node) {
|
|
117
|
-
if (node == null) return false;
|
|
118
|
-
const id = AST14.getFunctionId(node);
|
|
119
|
-
return id?.name != null && isReactHookName(id.name);
|
|
120
|
-
}
|
|
121
|
-
function isReactHookCall(node) {
|
|
122
|
-
if (node == null) return false;
|
|
123
|
-
if (node.type !== AST_NODE_TYPES.CallExpression) {
|
|
124
|
-
return false;
|
|
125
|
-
}
|
|
126
|
-
if (node.callee.type === AST_NODE_TYPES.Identifier) {
|
|
127
|
-
return isReactHookName(node.callee.name);
|
|
128
|
-
}
|
|
129
|
-
if (node.callee.type === AST_NODE_TYPES.MemberExpression) {
|
|
130
|
-
return node.callee.property.type === AST_NODE_TYPES.Identifier && isReactHookName(node.callee.property.name);
|
|
131
|
-
}
|
|
132
|
-
return false;
|
|
133
|
-
}
|
|
134
|
-
function isReactHookCallWithName(context, node) {
|
|
135
|
-
if (node == null || node.type !== AST_NODE_TYPES.CallExpression) return constFalse;
|
|
136
|
-
const {
|
|
137
|
-
importSource = DEFAULT_ESLINT_REACT_SETTINGS.importSource,
|
|
138
|
-
skipImportCheck = true
|
|
139
|
-
} = coerceSettings(context.settings);
|
|
140
|
-
const initialScope = context.sourceCode.getScope(node);
|
|
141
|
-
return (name) => {
|
|
142
|
-
switch (true) {
|
|
143
|
-
case (node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === name):
|
|
144
|
-
return skipImportCheck || isInitializedFromReact(name, importSource, initialScope);
|
|
145
|
-
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):
|
|
146
|
-
return skipImportCheck || isInitializedFromReact(node.callee.object.name, importSource, initialScope);
|
|
147
|
-
default:
|
|
148
|
-
return false;
|
|
149
|
-
}
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
function isReactHookCallWithNameLoose(node) {
|
|
153
|
-
if (node == null || node.type !== AST_NODE_TYPES.CallExpression) return constFalse;
|
|
154
|
-
return (name) => {
|
|
155
|
-
switch (node.callee.type) {
|
|
156
|
-
case AST_NODE_TYPES.Identifier:
|
|
157
|
-
return node.callee.name === name;
|
|
158
|
-
case AST_NODE_TYPES.MemberExpression:
|
|
159
|
-
return node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === name;
|
|
160
|
-
default:
|
|
161
|
-
return false;
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
function isReactHookCallWithNameAlias(context, name, alias = []) {
|
|
166
|
-
const {
|
|
167
|
-
importSource = DEFAULT_ESLINT_REACT_SETTINGS.importSource,
|
|
168
|
-
skipImportCheck = true
|
|
169
|
-
} = coerceSettings(context.settings);
|
|
170
|
-
return (node) => {
|
|
171
|
-
const initialScope = context.sourceCode.getScope(node);
|
|
172
|
-
switch (true) {
|
|
173
|
-
case (node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === name):
|
|
174
|
-
return skipImportCheck || isInitializedFromReact(name, importSource, initialScope);
|
|
175
|
-
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):
|
|
176
|
-
return skipImportCheck || isInitializedFromReact(node.callee.object.name, importSource, initialScope);
|
|
177
|
-
default:
|
|
178
|
-
return alias.some(isReactHookCallWithNameLoose(node));
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
function isUseEffectCallLoose(node) {
|
|
183
|
-
if (node == null) return false;
|
|
184
|
-
if (node.type !== AST_NODE_TYPES.CallExpression) {
|
|
185
|
-
return false;
|
|
186
|
-
}
|
|
187
|
-
switch (node.callee.type) {
|
|
188
|
-
case AST_NODE_TYPES.Identifier:
|
|
189
|
-
return /^use\w*Effect$/u.test(node.callee.name);
|
|
190
|
-
case AST_NODE_TYPES.MemberExpression:
|
|
191
|
-
return node.callee.property.type === AST_NODE_TYPES.Identifier && /^use\w*Effect$/u.test(node.callee.property.name);
|
|
192
|
-
default:
|
|
193
|
-
return false;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
var isUseCall = flip(isReactHookCallWithName)("use");
|
|
197
|
-
var isUseActionStateCall = flip(isReactHookCallWithName)("useActionState");
|
|
198
|
-
var isUseCallbackCall = flip(isReactHookCallWithName)("useCallback");
|
|
199
|
-
var isUseContextCall = flip(isReactHookCallWithName)("useContext");
|
|
200
|
-
var isUseDebugValueCall = flip(isReactHookCallWithName)("useDebugValue");
|
|
201
|
-
var isUseDeferredValueCall = flip(isReactHookCallWithName)("useDeferredValue");
|
|
202
|
-
var isUseEffectCall = flip(isReactHookCallWithName)("useEffect");
|
|
203
|
-
var isUseFormStatusCall = flip(isReactHookCallWithName)("useFormStatus");
|
|
204
|
-
var isUseIdCall = flip(isReactHookCallWithName)("useId");
|
|
205
|
-
var isUseImperativeHandleCall = flip(isReactHookCallWithName)("useImperativeHandle");
|
|
206
|
-
var isUseInsertionEffectCall = flip(isReactHookCallWithName)("useInsertionEffect");
|
|
207
|
-
var isUseLayoutEffectCall = flip(isReactHookCallWithName)("useLayoutEffect");
|
|
208
|
-
var isUseMemoCall = flip(isReactHookCallWithName)("useMemo");
|
|
209
|
-
var isUseOptimisticCall = flip(isReactHookCallWithName)("useOptimistic");
|
|
210
|
-
var isUseReducerCall = flip(isReactHookCallWithName)("useReducer");
|
|
211
|
-
var isUseRefCall = flip(isReactHookCallWithName)("useRef");
|
|
212
|
-
var isUseStateCall = flip(isReactHookCallWithName)("useState");
|
|
213
|
-
var isUseSyncExternalStoreCall = flip(isReactHookCallWithName)("useSyncExternalStore");
|
|
214
|
-
var isUseTransitionCall = flip(isReactHookCallWithName)("useTransition");
|
|
215
|
-
|
|
216
|
-
// src/hook/hook-collector.ts
|
|
217
|
-
function useHookCollector() {
|
|
218
|
-
const hooks = /* @__PURE__ */ new Map();
|
|
219
|
-
const functionEntries = [];
|
|
220
|
-
const onFunctionEnter = (node) => {
|
|
221
|
-
const id = AST14.getFunctionId(node);
|
|
222
|
-
const key = getId();
|
|
223
|
-
const name = id?.name;
|
|
224
|
-
if (name != null && isReactHookName(name)) {
|
|
225
|
-
functionEntries.push({ key, node, isHook: true });
|
|
226
|
-
hooks.set(key, {
|
|
227
|
-
id,
|
|
228
|
-
key,
|
|
229
|
-
kind: "function",
|
|
230
|
-
name,
|
|
231
|
-
node,
|
|
232
|
-
flag: 0n,
|
|
233
|
-
hint: 0n,
|
|
234
|
-
hookCalls: []
|
|
235
|
-
});
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
functionEntries.push({ key, node, isHook: false });
|
|
239
|
-
};
|
|
240
|
-
const onFunctionExit = () => {
|
|
241
|
-
functionEntries.pop();
|
|
242
|
-
};
|
|
243
|
-
const ctx = {
|
|
244
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
245
|
-
getAllHooks(node) {
|
|
246
|
-
return hooks;
|
|
247
|
-
}
|
|
248
|
-
};
|
|
249
|
-
const listeners = {
|
|
250
|
-
":function[type]": onFunctionEnter,
|
|
251
|
-
":function[type]:exit": onFunctionExit,
|
|
252
|
-
"CallExpression[type]"(node) {
|
|
253
|
-
if (!isReactHookCall(node)) {
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
const fEntry = functionEntries.at(-1);
|
|
257
|
-
if (fEntry?.key == null) {
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
const hook = hooks.get(fEntry.key);
|
|
261
|
-
if (hook == null) {
|
|
262
|
-
return;
|
|
263
|
-
}
|
|
264
|
-
hook.hookCalls.push(node);
|
|
265
|
-
}
|
|
266
|
-
};
|
|
267
|
-
return { ctx, listeners };
|
|
268
|
-
}
|
|
269
|
-
function stringifyJsx(node) {
|
|
270
|
-
switch (node.type) {
|
|
271
|
-
case AST_NODE_TYPES.JSXIdentifier:
|
|
272
|
-
return node.name;
|
|
273
|
-
case AST_NODE_TYPES.JSXNamespacedName:
|
|
274
|
-
return `${node.namespace.name}:${node.name.name}`;
|
|
275
|
-
case AST_NODE_TYPES.JSXMemberExpression:
|
|
276
|
-
return `${stringifyJsx(node.object)}.${stringifyJsx(node.property)}`;
|
|
277
|
-
case AST_NODE_TYPES.JSXText:
|
|
278
|
-
return node.value;
|
|
279
|
-
case AST_NODE_TYPES.JSXOpeningElement:
|
|
280
|
-
return `<${stringifyJsx(node.name)}>`;
|
|
281
|
-
case AST_NODE_TYPES.JSXClosingElement:
|
|
282
|
-
return `</${stringifyJsx(node.name)}>`;
|
|
283
|
-
case AST_NODE_TYPES.JSXOpeningFragment:
|
|
284
|
-
return "<>";
|
|
285
|
-
case AST_NODE_TYPES.JSXClosingFragment:
|
|
286
|
-
return "</>";
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// src/jsx/jsx-attribute-name.ts
|
|
291
|
-
function getAttributeName(context, node) {
|
|
292
|
-
return stringifyJsx(node.name);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// src/jsx/jsx-attribute.ts
|
|
296
|
-
function getAttribute(context, name, attributes, initialScope) {
|
|
297
|
-
return attributes.findLast((attr) => {
|
|
298
|
-
if (attr.type === AST_NODE_TYPES.JSXAttribute) {
|
|
299
|
-
return getAttributeName(context, attr) === name;
|
|
300
|
-
}
|
|
301
|
-
if (initialScope == null) return false;
|
|
302
|
-
switch (attr.argument.type) {
|
|
303
|
-
case AST_NODE_TYPES.Identifier: {
|
|
304
|
-
const variable = VAR3.findVariable(attr.argument.name, initialScope);
|
|
305
|
-
const variableNode = VAR3.getVariableInitNode(variable, 0);
|
|
306
|
-
if (variableNode?.type === AST_NODE_TYPES.ObjectExpression) {
|
|
307
|
-
return VAR3.findPropertyInProperties(name, variableNode.properties, initialScope) != null;
|
|
308
|
-
}
|
|
309
|
-
return false;
|
|
310
|
-
}
|
|
311
|
-
case AST_NODE_TYPES.ObjectExpression:
|
|
312
|
-
return VAR3.findPropertyInProperties(name, attr.argument.properties, initialScope) != null;
|
|
313
|
-
}
|
|
314
|
-
return false;
|
|
315
|
-
});
|
|
316
|
-
}
|
|
317
|
-
function getAttributeValue(context, node, name) {
|
|
318
|
-
const initialScope = context.sourceCode.getScope(node);
|
|
319
|
-
switch (node.type) {
|
|
320
|
-
case AST_NODE_TYPES.JSXAttribute:
|
|
321
|
-
if (node.value?.type === AST_NODE_TYPES.Literal) {
|
|
322
|
-
return {
|
|
323
|
-
kind: "some",
|
|
324
|
-
node: node.value,
|
|
325
|
-
initialScope,
|
|
326
|
-
value: node.value.value
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
if (node.value?.type === AST_NODE_TYPES.JSXExpressionContainer) {
|
|
330
|
-
return VAR3.toStaticValue({
|
|
331
|
-
kind: "lazy",
|
|
332
|
-
node: node.value.expression,
|
|
333
|
-
initialScope
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
return { kind: "none", node, initialScope };
|
|
337
|
-
case AST_NODE_TYPES.JSXSpreadAttribute: {
|
|
338
|
-
const staticValue = VAR3.toStaticValue({
|
|
339
|
-
kind: "lazy",
|
|
340
|
-
node: node.argument,
|
|
341
|
-
initialScope
|
|
342
|
-
});
|
|
343
|
-
if (staticValue.kind === "none") {
|
|
344
|
-
return staticValue;
|
|
345
|
-
}
|
|
346
|
-
return match(staticValue.value).with({ [name]: P.select(P.any) }, (value) => ({
|
|
347
|
-
kind: "some",
|
|
348
|
-
node: node.argument,
|
|
349
|
-
initialScope,
|
|
350
|
-
value
|
|
351
|
-
})).otherwise(() => ({ kind: "none", node, initialScope }));
|
|
352
|
-
}
|
|
353
|
-
default:
|
|
354
|
-
return { kind: "none", node, initialScope };
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
// src/jsx/jsx-detection-hint.ts
|
|
359
|
-
var JSXDetectionHint = {
|
|
360
|
-
None: 0n,
|
|
361
|
-
SkipUndefined: 1n << 0n,
|
|
362
|
-
SkipNullLiteral: 1n << 1n,
|
|
363
|
-
SkipBooleanLiteral: 1n << 2n,
|
|
364
|
-
SkipStringLiteral: 1n << 3n,
|
|
365
|
-
SkipNumberLiteral: 1n << 4n,
|
|
366
|
-
SkipBigIntLiteral: 1n << 5n,
|
|
367
|
-
SkipEmptyArray: 1n << 6n,
|
|
368
|
-
SkipCreateElement: 1n << 7n,
|
|
369
|
-
StrictArray: 1n << 8n,
|
|
370
|
-
StrictLogical: 1n << 9n,
|
|
371
|
-
StrictConditional: 1n << 10n
|
|
372
|
-
};
|
|
373
|
-
var DEFAULT_JSX_DETECTION_HINT = 0n | JSXDetectionHint.SkipUndefined | JSXDetectionHint.SkipBooleanLiteral;
|
|
374
|
-
|
|
375
|
-
// src/jsx/jsx-detection.ts
|
|
376
|
-
function isJsxText(node) {
|
|
377
|
-
if (node == null) return false;
|
|
378
|
-
return node.type === AST_NODE_TYPES.JSXText || node.type === AST_NODE_TYPES.Literal;
|
|
379
|
-
}
|
|
380
|
-
function isJsxLike(code, node, hint = DEFAULT_JSX_DETECTION_HINT) {
|
|
381
|
-
if (node == null) return false;
|
|
382
|
-
if (AST14.isJSX(node)) return true;
|
|
383
|
-
switch (node.type) {
|
|
384
|
-
case AST_NODE_TYPES.Literal: {
|
|
385
|
-
switch (typeof node.value) {
|
|
386
|
-
case "boolean":
|
|
387
|
-
return !(hint & JSXDetectionHint.SkipBooleanLiteral);
|
|
388
|
-
case "string":
|
|
389
|
-
return !(hint & JSXDetectionHint.SkipStringLiteral);
|
|
390
|
-
case "number":
|
|
391
|
-
return !(hint & JSXDetectionHint.SkipNumberLiteral);
|
|
392
|
-
case "bigint":
|
|
393
|
-
return !(hint & JSXDetectionHint.SkipBigIntLiteral);
|
|
394
|
-
}
|
|
395
|
-
if (node.value == null) {
|
|
396
|
-
return !(hint & JSXDetectionHint.SkipNullLiteral);
|
|
397
|
-
}
|
|
398
|
-
return false;
|
|
399
|
-
}
|
|
400
|
-
case AST_NODE_TYPES.TemplateLiteral: {
|
|
401
|
-
return !(hint & JSXDetectionHint.SkipStringLiteral);
|
|
402
|
-
}
|
|
403
|
-
case AST_NODE_TYPES.ArrayExpression: {
|
|
404
|
-
if (hint & JSXDetectionHint.StrictArray) {
|
|
405
|
-
return node.elements.every((n) => isJsxLike(code, n, hint));
|
|
406
|
-
}
|
|
407
|
-
return node.elements.some((n) => isJsxLike(code, n, hint));
|
|
408
|
-
}
|
|
409
|
-
case AST_NODE_TYPES.LogicalExpression: {
|
|
410
|
-
if (hint & JSXDetectionHint.StrictLogical) {
|
|
411
|
-
return isJsxLike(code, node.left, hint) && isJsxLike(code, node.right, hint);
|
|
412
|
-
}
|
|
413
|
-
return isJsxLike(code, node.left, hint) || isJsxLike(code, node.right, hint);
|
|
414
|
-
}
|
|
415
|
-
case AST_NODE_TYPES.ConditionalExpression: {
|
|
416
|
-
let leftHasJSX2 = function(node2) {
|
|
417
|
-
if (Array.isArray(node2.consequent)) {
|
|
418
|
-
if (node2.consequent.length === 0) {
|
|
419
|
-
return !(hint & JSXDetectionHint.SkipEmptyArray);
|
|
420
|
-
}
|
|
421
|
-
if (hint & JSXDetectionHint.StrictArray) {
|
|
422
|
-
return node2.consequent.every((n) => isJsxLike(code, n, hint));
|
|
423
|
-
}
|
|
424
|
-
return node2.consequent.some((n) => isJsxLike(code, n, hint));
|
|
425
|
-
}
|
|
426
|
-
return isJsxLike(code, node2.consequent, hint);
|
|
427
|
-
}, rightHasJSX2 = function(node2) {
|
|
428
|
-
return isJsxLike(code, node2.alternate, hint);
|
|
429
|
-
};
|
|
430
|
-
if (hint & JSXDetectionHint.StrictConditional) {
|
|
431
|
-
return leftHasJSX2(node) && rightHasJSX2(node);
|
|
432
|
-
}
|
|
433
|
-
return leftHasJSX2(node) || rightHasJSX2(node);
|
|
434
|
-
}
|
|
435
|
-
case AST_NODE_TYPES.SequenceExpression: {
|
|
436
|
-
const exp = node.expressions.at(-1);
|
|
437
|
-
return isJsxLike(code, exp, hint);
|
|
438
|
-
}
|
|
439
|
-
case AST_NODE_TYPES.CallExpression: {
|
|
440
|
-
if (hint & JSXDetectionHint.SkipCreateElement) {
|
|
441
|
-
return false;
|
|
442
|
-
}
|
|
443
|
-
switch (node.callee.type) {
|
|
444
|
-
case AST_NODE_TYPES.Identifier:
|
|
445
|
-
return node.callee.name === "createElement";
|
|
446
|
-
case AST_NODE_TYPES.MemberExpression:
|
|
447
|
-
return node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === "createElement";
|
|
448
|
-
}
|
|
449
|
-
return false;
|
|
450
|
-
}
|
|
451
|
-
case AST_NODE_TYPES.Identifier: {
|
|
452
|
-
const { name } = node;
|
|
453
|
-
if (name === "undefined") {
|
|
454
|
-
return !(hint & JSXDetectionHint.SkipUndefined);
|
|
455
|
-
}
|
|
456
|
-
if (AST14.isJSXTagNameExpression(node)) {
|
|
457
|
-
return true;
|
|
458
|
-
}
|
|
459
|
-
const variable = VAR3.findVariable(name, code.getScope(node));
|
|
460
|
-
const variableNode = variable && VAR3.getVariableInitNode(variable, 0);
|
|
461
|
-
return !!variableNode && isJsxLike(code, variableNode, hint);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
return false;
|
|
465
|
-
}
|
|
466
|
-
function getElementType(context, node) {
|
|
467
|
-
if (node.type === AST_NODE_TYPES.JSXFragment) {
|
|
468
|
-
return "";
|
|
469
|
-
}
|
|
470
|
-
return stringifyJsx(node.openingElement.name);
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
// src/jsx/jsx-has.ts
|
|
474
|
-
function hasAttribute(context, name, attributes, initialScope) {
|
|
475
|
-
return getAttribute(context, name, attributes, initialScope) != null;
|
|
476
|
-
}
|
|
477
|
-
function hasAnyAttribute(context, names, attributes, initialScope) {
|
|
478
|
-
return names.some((n) => hasAttribute(context, n, attributes, initialScope));
|
|
479
|
-
}
|
|
480
|
-
function hasEveryAttribute(context, names, attributes, initialScope) {
|
|
481
|
-
return names.every((n) => hasAttribute(context, n, attributes, initialScope));
|
|
482
|
-
}
|
|
483
|
-
function findParentAttribute(node, test = constTrue) {
|
|
484
|
-
const guard = (node2) => {
|
|
485
|
-
return node2.type === AST_NODE_TYPES.JSXAttribute && test(node2);
|
|
486
|
-
};
|
|
487
|
-
return AST14.findParentNode(node, guard);
|
|
488
|
-
}
|
|
489
|
-
function isHostElement(context, node) {
|
|
490
|
-
return node.type === AST_NODE_TYPES.JSXElement && node.openingElement.name.type === AST_NODE_TYPES.JSXIdentifier && /^[a-z]/u.test(node.openingElement.name.name);
|
|
491
|
-
}
|
|
492
|
-
function isKeyedElement(context, node, initialScope) {
|
|
493
|
-
return node.type === AST_NODE_TYPES.JSXElement && hasAttribute(context, "key", node.openingElement.attributes, initialScope);
|
|
494
|
-
}
|
|
495
|
-
function isFragmentElement(context, node, allowJSXFragment = false) {
|
|
496
|
-
if (node == null) return false;
|
|
497
|
-
if (node.type !== AST_NODE_TYPES.JSXElement && node.type !== AST_NODE_TYPES.JSXFragment) return false;
|
|
498
|
-
if (node.type === AST_NODE_TYPES.JSXFragment) return allowJSXFragment;
|
|
499
|
-
return getElementType(context, node).split(".").at(-1) === "Fragment";
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
// src/component/component-detection-hint.ts
|
|
503
|
-
var ComponentDetectionHint = {
|
|
504
|
-
/**
|
|
505
|
-
* 1n << 0n - 1n << 63n are reserved for JSXDetectionHint
|
|
506
|
-
*/
|
|
507
|
-
...JSXDetectionHint,
|
|
508
|
-
/**
|
|
509
|
-
* Skip function component created by React.memo
|
|
510
|
-
*/
|
|
511
|
-
SkipMemo: 1n << 64n,
|
|
512
|
-
/**
|
|
513
|
-
* Skip function component created by React.forwardRef
|
|
514
|
-
*/
|
|
515
|
-
SkipForwardRef: 1n << 65n,
|
|
516
|
-
/**
|
|
517
|
-
* Skip function component defined as array map argument
|
|
518
|
-
*/
|
|
519
|
-
SkipArrayMapArgument: 1n << 66n,
|
|
520
|
-
/**
|
|
521
|
-
* Skip function component defined on object method
|
|
522
|
-
*/
|
|
523
|
-
SkipObjectMethod: 1n << 67n,
|
|
524
|
-
/**
|
|
525
|
-
* Skip function component defined on class method
|
|
526
|
-
*/
|
|
527
|
-
SkipClassMethod: 1n << 68n,
|
|
528
|
-
/**
|
|
529
|
-
* Skip function component defined on class property
|
|
530
|
-
*/
|
|
531
|
-
SkipClassProperty: 1n << 69n
|
|
532
|
-
};
|
|
533
|
-
var DEFAULT_COMPONENT_DETECTION_HINT = 0n | ComponentDetectionHint.SkipBooleanLiteral | ComponentDetectionHint.SkipEmptyArray | ComponentDetectionHint.SkipArrayMapArgument | ComponentDetectionHint.SkipNumberLiteral | ComponentDetectionHint.SkipStringLiteral | ComponentDetectionHint.SkipUndefined | ComponentDetectionHint.StrictArray | ComponentDetectionHint.StrictConditional | ComponentDetectionHint.StrictLogical;
|
|
534
|
-
function isClassComponent(node) {
|
|
535
|
-
if ("superClass" in node && node.superClass != null) {
|
|
536
|
-
const re = /^(?:Pure)?Component$/u;
|
|
537
|
-
switch (true) {
|
|
538
|
-
case node.superClass.type === AST_NODE_TYPES.Identifier:
|
|
539
|
-
return re.test(node.superClass.name);
|
|
540
|
-
case (node.superClass.type === AST_NODE_TYPES.MemberExpression && node.superClass.property.type === AST_NODE_TYPES.Identifier):
|
|
541
|
-
return re.test(node.superClass.property.name);
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
return false;
|
|
545
|
-
}
|
|
546
|
-
function isPureComponent(node) {
|
|
547
|
-
if ("superClass" in node && node.superClass != null) {
|
|
548
|
-
const re = /^PureComponent$/u;
|
|
549
|
-
switch (true) {
|
|
550
|
-
case node.superClass.type === AST_NODE_TYPES.Identifier:
|
|
551
|
-
return re.test(node.superClass.name);
|
|
552
|
-
case (node.superClass.type === AST_NODE_TYPES.MemberExpression && node.superClass.property.type === AST_NODE_TYPES.Identifier):
|
|
553
|
-
return re.test(node.superClass.property.name);
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
return false;
|
|
557
|
-
}
|
|
558
|
-
function isRenderMethodLike(node) {
|
|
559
|
-
return AST14.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name.startsWith("render") && node.parent.parent.type === AST_NODE_TYPES.ClassDeclaration;
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
// src/component/component-definition.ts
|
|
563
|
-
var isFunctionOfClassMethod = isMatching({
|
|
564
|
-
type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
|
|
565
|
-
parent: AST_NODE_TYPES.MethodDefinition
|
|
566
|
-
});
|
|
567
|
-
var isFunctionOfClassProperty = isMatching({
|
|
568
|
-
type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
|
|
569
|
-
parent: AST_NODE_TYPES.Property
|
|
570
|
-
});
|
|
571
|
-
var isFunctionOfObjectMethod = isMatching({
|
|
572
|
-
type: P.union(AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression),
|
|
573
|
-
parent: {
|
|
574
|
-
type: AST_NODE_TYPES.Property,
|
|
575
|
-
parent: {
|
|
576
|
-
type: AST_NODE_TYPES.ObjectExpression
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
});
|
|
580
|
-
function isFunctionOfRenderMethod(node) {
|
|
581
|
-
if (!isRenderMethodLike(node.parent)) {
|
|
582
|
-
return false;
|
|
583
|
-
}
|
|
584
|
-
return isClassComponent(node.parent.parent.parent);
|
|
585
|
-
}
|
|
586
|
-
function isValidComponentDefinition(context, node, hint) {
|
|
587
|
-
if (isChildrenOfCreateElement(context, node) || isFunctionOfRenderMethod(node)) {
|
|
588
|
-
return false;
|
|
589
|
-
}
|
|
590
|
-
if (hint & ComponentDetectionHint.SkipObjectMethod && isFunctionOfObjectMethod(node.parent)) {
|
|
591
|
-
return false;
|
|
592
|
-
}
|
|
593
|
-
if (hint & ComponentDetectionHint.SkipClassMethod && isFunctionOfClassMethod(node.parent)) {
|
|
594
|
-
return false;
|
|
595
|
-
}
|
|
596
|
-
if (hint & ComponentDetectionHint.SkipClassProperty && isFunctionOfClassProperty(node.parent)) {
|
|
597
|
-
return false;
|
|
598
|
-
}
|
|
599
|
-
if (hint & ComponentDetectionHint.SkipArrayMapArgument && AST14.isArrayMapCall(node.parent)) {
|
|
600
|
-
return false;
|
|
601
|
-
}
|
|
602
|
-
const significantParent = AST14.findParentNode(
|
|
603
|
-
node,
|
|
604
|
-
AST14.isOneOf([
|
|
605
|
-
AST_NODE_TYPES.JSXExpressionContainer,
|
|
606
|
-
AST_NODE_TYPES.ArrowFunctionExpression,
|
|
607
|
-
AST_NODE_TYPES.FunctionExpression,
|
|
608
|
-
AST_NODE_TYPES.Property,
|
|
609
|
-
AST_NODE_TYPES.ClassBody
|
|
610
|
-
])
|
|
611
|
-
);
|
|
612
|
-
return significantParent == null || significantParent.type !== AST_NODE_TYPES.JSXExpressionContainer;
|
|
613
|
-
}
|
|
614
|
-
function isComponentWrapperCall(context, node) {
|
|
615
|
-
if (node.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
616
|
-
return isMemoCall(context, node) || isForwardRefCall(context, node);
|
|
617
|
-
}
|
|
618
|
-
function isComponentWrapperCallLoose(context, node) {
|
|
619
|
-
if (node.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
620
|
-
return isComponentWrapperCall(context, node) || isUseCallbackCall(context, node);
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
// src/component/component-id.ts
|
|
624
|
-
function getFunctionComponentId(context, node) {
|
|
625
|
-
const functionId = AST14.getFunctionId(node);
|
|
626
|
-
if (functionId != null) {
|
|
627
|
-
return functionId;
|
|
628
|
-
}
|
|
629
|
-
const { parent } = node;
|
|
630
|
-
if (parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCallLoose(context, parent) && parent.parent.type === AST_NODE_TYPES.VariableDeclarator && parent.parent.id.type === AST_NODE_TYPES.Identifier) {
|
|
631
|
-
return parent.parent.id;
|
|
632
|
-
}
|
|
633
|
-
if (parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCallLoose(context, parent) && parent.parent.type === AST_NODE_TYPES.CallExpression && isComponentWrapperCallLoose(context, parent.parent) && parent.parent.parent.type === AST_NODE_TYPES.VariableDeclarator && parent.parent.parent.id.type === AST_NODE_TYPES.Identifier) {
|
|
634
|
-
return parent.parent.parent.id;
|
|
635
|
-
}
|
|
636
|
-
return _;
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
// src/component/component-flag.ts
|
|
640
|
-
var ComponentFlag = {
|
|
641
|
-
None: 0n,
|
|
642
|
-
PureComponent: 1n << 0n,
|
|
643
|
-
CreateElement: 1n << 1n,
|
|
644
|
-
Memo: 1n << 2n,
|
|
645
|
-
ForwardRef: 1n << 3n,
|
|
646
|
-
Async: 1n << 4n
|
|
647
|
-
};
|
|
648
|
-
|
|
649
|
-
// src/component/component-init-path.ts
|
|
650
|
-
function getComponentFlagFromInitPath(initPath) {
|
|
651
|
-
let flag = ComponentFlag.None;
|
|
652
|
-
if (initPath != null && AST14.hasCallInFunctionInitPath("memo", initPath)) {
|
|
653
|
-
flag |= ComponentFlag.Memo;
|
|
654
|
-
}
|
|
655
|
-
if (initPath != null && AST14.hasCallInFunctionInitPath("forwardRef", initPath)) {
|
|
656
|
-
flag |= ComponentFlag.ForwardRef;
|
|
657
|
-
}
|
|
658
|
-
return flag;
|
|
659
|
-
}
|
|
660
|
-
function isComponentName(name) {
|
|
661
|
-
return RegExp.COMPONENT_NAME.test(name);
|
|
662
|
-
}
|
|
663
|
-
function isComponentNameLoose(name) {
|
|
664
|
-
return RegExp.COMPONENT_NAME_LOOSE.test(name);
|
|
665
|
-
}
|
|
666
|
-
function getComponentNameFromId(id) {
|
|
667
|
-
if (id == null) return _;
|
|
668
|
-
return Array.isArray(id) ? id.map((n) => n.name).join(".") : id.name;
|
|
669
|
-
}
|
|
670
|
-
function hasNoneOrLooseComponentName(context, fn) {
|
|
671
|
-
const id = getFunctionComponentId(context, fn);
|
|
672
|
-
if (id == null) return true;
|
|
673
|
-
const name = Array.isArray(id) ? id.at(-1)?.name : id.name;
|
|
674
|
-
return name != null && isComponentNameLoose(name);
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
// src/component/component-collector.ts
|
|
678
|
-
function useComponentCollector(context, options = {}) {
|
|
679
|
-
const {
|
|
680
|
-
collectDisplayName = false,
|
|
681
|
-
collectHookCalls = false,
|
|
682
|
-
hint = DEFAULT_COMPONENT_DETECTION_HINT
|
|
683
|
-
} = options;
|
|
684
|
-
const components = /* @__PURE__ */ new Map();
|
|
685
|
-
const functionEntries = [];
|
|
686
|
-
const getCurrentEntry = () => functionEntries.at(-1);
|
|
687
|
-
const onFunctionEnter = (node) => {
|
|
688
|
-
const key = getId();
|
|
689
|
-
functionEntries.push({ key, node, hookCalls: [], isComponent: false });
|
|
690
|
-
};
|
|
691
|
-
const onFunctionExit = () => {
|
|
692
|
-
const entry = functionEntries.at(-1);
|
|
693
|
-
if (entry == null) return;
|
|
694
|
-
if (!entry.isComponent) return functionEntries.pop();
|
|
695
|
-
const shouldDrop = AST14.getNestedReturnStatements(entry.node.body).slice().reverse().some((r) => {
|
|
696
|
-
return context.sourceCode.getScope(r).block === entry.node && r.argument != null && !isJsxLike(context.sourceCode, r.argument, hint);
|
|
697
|
-
});
|
|
698
|
-
if (shouldDrop) {
|
|
699
|
-
components.delete(entry.key);
|
|
700
|
-
}
|
|
701
|
-
return functionEntries.pop();
|
|
702
|
-
};
|
|
703
|
-
const ctx = {
|
|
704
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
705
|
-
getAllComponents(node) {
|
|
706
|
-
return components;
|
|
707
|
-
},
|
|
708
|
-
getCurrentEntries() {
|
|
709
|
-
return [...functionEntries];
|
|
710
|
-
},
|
|
711
|
-
getCurrentEntry
|
|
712
|
-
};
|
|
713
|
-
const listeners = {
|
|
714
|
-
":function[type]": onFunctionEnter,
|
|
715
|
-
":function[type]:exit": onFunctionExit,
|
|
716
|
-
"ArrowFunctionExpression[body.type!='BlockStatement']"() {
|
|
717
|
-
const entry = getCurrentEntry();
|
|
718
|
-
if (entry == null) return;
|
|
719
|
-
const { body } = entry.node;
|
|
720
|
-
const isComponent = hasNoneOrLooseComponentName(context, entry.node) && isJsxLike(context.sourceCode, body, hint) && isValidComponentDefinition(context, entry.node, hint);
|
|
721
|
-
if (!isComponent) return;
|
|
722
|
-
const initPath = AST14.getFunctionInitPath(entry.node);
|
|
723
|
-
const id = getFunctionComponentId(context, entry.node);
|
|
724
|
-
const name = getComponentNameFromId(id);
|
|
725
|
-
const key = getId();
|
|
726
|
-
components.set(key, {
|
|
727
|
-
id,
|
|
728
|
-
key,
|
|
729
|
-
kind: "function",
|
|
730
|
-
name,
|
|
731
|
-
node: entry.node,
|
|
732
|
-
displayName: _,
|
|
733
|
-
flag: getComponentFlagFromInitPath(initPath),
|
|
734
|
-
hint,
|
|
735
|
-
hookCalls: entry.hookCalls,
|
|
736
|
-
initPath
|
|
737
|
-
});
|
|
738
|
-
},
|
|
739
|
-
...collectDisplayName ? {
|
|
740
|
-
[Selector.DISPLAY_NAME_ASSIGNMENT_EXPRESSION](node) {
|
|
741
|
-
const { left, right } = node;
|
|
742
|
-
if (left.type !== AST_NODE_TYPES.MemberExpression) return;
|
|
743
|
-
const componentName = left.object.type === AST_NODE_TYPES.Identifier ? left.object.name : _;
|
|
744
|
-
const component = [...components.values()].findLast(({ name }) => name != null && name === componentName);
|
|
745
|
-
if (component == null) return;
|
|
746
|
-
component.displayName = right;
|
|
747
|
-
}
|
|
748
|
-
} : {},
|
|
749
|
-
...collectHookCalls ? {
|
|
750
|
-
"CallExpression[type]:exit"(node) {
|
|
751
|
-
if (!isReactHookCall(node)) return;
|
|
752
|
-
const entry = getCurrentEntry();
|
|
753
|
-
if (entry == null) return;
|
|
754
|
-
entry.hookCalls.push(node);
|
|
755
|
-
}
|
|
756
|
-
} : {},
|
|
757
|
-
"ReturnStatement[type]"(node) {
|
|
758
|
-
const entry = getCurrentEntry();
|
|
759
|
-
if (entry == null) return;
|
|
760
|
-
const isComponent = hasNoneOrLooseComponentName(context, entry.node) && isJsxLike(context.sourceCode, node.argument, hint) && isValidComponentDefinition(context, entry.node, hint);
|
|
761
|
-
if (!isComponent) return;
|
|
762
|
-
entry.isComponent = true;
|
|
763
|
-
const initPath = AST14.getFunctionInitPath(entry.node);
|
|
764
|
-
const id = getFunctionComponentId(context, entry.node);
|
|
765
|
-
const name = getComponentNameFromId(id);
|
|
766
|
-
components.set(entry.key, {
|
|
767
|
-
id,
|
|
768
|
-
key: entry.key,
|
|
769
|
-
kind: "function",
|
|
770
|
-
name,
|
|
771
|
-
node: entry.node,
|
|
772
|
-
displayName: _,
|
|
773
|
-
flag: getComponentFlagFromInitPath(initPath),
|
|
774
|
-
hint,
|
|
775
|
-
hookCalls: entry.hookCalls,
|
|
776
|
-
initPath
|
|
777
|
-
});
|
|
778
|
-
}
|
|
779
|
-
};
|
|
780
|
-
return { ctx, listeners };
|
|
781
|
-
}
|
|
782
|
-
function useComponentCollectorLegacy() {
|
|
783
|
-
const components = /* @__PURE__ */ new Map();
|
|
784
|
-
const ctx = {
|
|
785
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
786
|
-
getAllComponents(node) {
|
|
787
|
-
return components;
|
|
788
|
-
}
|
|
789
|
-
};
|
|
790
|
-
const collect = (node) => {
|
|
791
|
-
if (!isClassComponent(node)) {
|
|
792
|
-
return;
|
|
793
|
-
}
|
|
794
|
-
const id = AST14.getClassId(node);
|
|
795
|
-
const key = getId();
|
|
796
|
-
const flag = isPureComponent(node) ? ComponentFlag.PureComponent : ComponentFlag.None;
|
|
797
|
-
components.set(
|
|
798
|
-
key,
|
|
799
|
-
{
|
|
800
|
-
id,
|
|
801
|
-
key,
|
|
802
|
-
kind: "class",
|
|
803
|
-
name: id?.name,
|
|
804
|
-
node,
|
|
805
|
-
// TODO: Get displayName of class component
|
|
806
|
-
displayName: _,
|
|
807
|
-
flag,
|
|
808
|
-
hint: 0n,
|
|
809
|
-
// TODO: Get methods of class component
|
|
810
|
-
methods: []
|
|
811
|
-
}
|
|
812
|
-
);
|
|
813
|
-
};
|
|
814
|
-
const listeners = {
|
|
815
|
-
"ClassDeclaration[type]": collect,
|
|
816
|
-
"ClassExpression[type]": collect
|
|
817
|
-
};
|
|
818
|
-
return { ctx, listeners };
|
|
819
|
-
}
|
|
820
|
-
function isComponentDidCatch(node) {
|
|
821
|
-
return AST14.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidCatch";
|
|
822
|
-
}
|
|
823
|
-
function isComponentDidMount(node) {
|
|
824
|
-
return AST14.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidMount";
|
|
825
|
-
}
|
|
826
|
-
function isComponentDidUpdate(node) {
|
|
827
|
-
return AST14.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentDidUpdate";
|
|
828
|
-
}
|
|
829
|
-
function isComponentWillMount(node) {
|
|
830
|
-
return AST14.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillMount";
|
|
831
|
-
}
|
|
832
|
-
function isComponentWillReceiveProps(node) {
|
|
833
|
-
return AST14.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillReceiveProps";
|
|
834
|
-
}
|
|
835
|
-
function isComponentWillUnmount(node) {
|
|
836
|
-
return AST14.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillUnmount";
|
|
837
|
-
}
|
|
838
|
-
function isComponentWillUpdate(node) {
|
|
839
|
-
return AST14.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "componentWillUpdate";
|
|
840
|
-
}
|
|
841
|
-
function isGetChildContext(node) {
|
|
842
|
-
return AST14.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getChildContext";
|
|
843
|
-
}
|
|
844
|
-
function isGetDefaultProps(node) {
|
|
845
|
-
return AST14.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDefaultProps";
|
|
846
|
-
}
|
|
847
|
-
function isGetInitialState(node) {
|
|
848
|
-
return AST14.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getInitialState";
|
|
849
|
-
}
|
|
850
|
-
function isGetSnapshotBeforeUpdate(node) {
|
|
851
|
-
return AST14.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getSnapshotBeforeUpdate";
|
|
852
|
-
}
|
|
853
|
-
function isShouldComponentUpdate(node) {
|
|
854
|
-
return AST14.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "shouldComponentUpdate";
|
|
855
|
-
}
|
|
856
|
-
function isUnsafeComponentWillMount(node) {
|
|
857
|
-
return AST14.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "UNSAFE_componentWillMount";
|
|
858
|
-
}
|
|
859
|
-
function isUnsafeComponentWillReceiveProps(node) {
|
|
860
|
-
return AST14.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "UNSAFE_componentWillReceiveProps";
|
|
861
|
-
}
|
|
862
|
-
function isUnsafeComponentWillUpdate(node) {
|
|
863
|
-
return AST14.isMethodOrProperty(node) && !node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "UNSAFE_componentWillUpdate";
|
|
864
|
-
}
|
|
865
|
-
function isGetDerivedStateFromProps(node) {
|
|
866
|
-
return AST14.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromProps";
|
|
867
|
-
}
|
|
868
|
-
function isGetDerivedStateFromError(node) {
|
|
869
|
-
return AST14.isMethodOrProperty(node) && node.static && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "getDerivedStateFromError";
|
|
870
|
-
}
|
|
871
|
-
var ComponentPhaseRelevance = birecord({
|
|
872
|
-
mount: "unmount",
|
|
873
|
-
setup: "cleanup"
|
|
874
|
-
});
|
|
875
|
-
var isInversePhase = dual(2, (a, b) => ComponentPhaseRelevance.get(a) === b);
|
|
876
|
-
function isRenderLike(node) {
|
|
877
|
-
return AST14.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "render" && node.parent.parent.type === AST_NODE_TYPES.ClassDeclaration;
|
|
878
|
-
}
|
|
879
|
-
function isFunctionOfRender(node) {
|
|
880
|
-
if (!isRenderLike(node.parent)) {
|
|
881
|
-
return false;
|
|
882
|
-
}
|
|
883
|
-
return isClassComponent(node.parent.parent.parent);
|
|
884
|
-
}
|
|
885
|
-
function isRenderFunctionLoose(context, node) {
|
|
886
|
-
const { body, parent } = node;
|
|
887
|
-
if (AST14.getFunctionId(node)?.name.startsWith("render")) {
|
|
888
|
-
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");
|
|
889
|
-
}
|
|
890
|
-
return isJsxLike(
|
|
891
|
-
context.sourceCode,
|
|
892
|
-
body,
|
|
893
|
-
JSXDetectionHint.SkipNullLiteral | JSXDetectionHint.SkipUndefined | JSXDetectionHint.StrictLogical | JSXDetectionHint.StrictConditional
|
|
894
|
-
);
|
|
895
|
-
}
|
|
896
|
-
function isRenderPropLoose(context, node) {
|
|
897
|
-
if (node.name.type !== AST_NODE_TYPES.JSXIdentifier) {
|
|
898
|
-
return false;
|
|
899
|
-
}
|
|
900
|
-
return node.name.name.startsWith("render") && node.value?.type === AST_NODE_TYPES.JSXExpressionContainer && AST14.isFunction(node.value.expression) && isRenderFunctionLoose(context, node.value.expression);
|
|
901
|
-
}
|
|
902
|
-
function isDirectValueOfRenderPropertyLoose(node) {
|
|
903
|
-
const matching = (node2) => {
|
|
904
|
-
return node2.type === AST_NODE_TYPES.Property && node2.key.type === AST_NODE_TYPES.Identifier && node2.key.name.startsWith("render");
|
|
905
|
-
};
|
|
906
|
-
return matching(node) || node.parent != null && matching(node.parent);
|
|
907
|
-
}
|
|
908
|
-
function isDeclaredInRenderPropLoose(node) {
|
|
909
|
-
if (isDirectValueOfRenderPropertyLoose(node)) {
|
|
910
|
-
return true;
|
|
911
|
-
}
|
|
912
|
-
const parent = AST14.findParentNode(node, AST14.is(AST_NODE_TYPES.JSXExpressionContainer))?.parent;
|
|
913
|
-
if (parent?.type !== AST_NODE_TYPES.JSXAttribute) {
|
|
914
|
-
return false;
|
|
915
|
-
}
|
|
916
|
-
return parent.name.type === AST_NODE_TYPES.JSXIdentifier && parent.name.name.startsWith("render");
|
|
917
|
-
}
|
|
918
|
-
function isThisSetState(node) {
|
|
919
|
-
const { callee } = node;
|
|
920
|
-
return callee.type === AST_NODE_TYPES.MemberExpression && AST14.isThisExpression(callee.object) && callee.property.type === AST_NODE_TYPES.Identifier && callee.property.name === "setState";
|
|
921
|
-
}
|
|
922
|
-
function isAssignmentToThisState(node) {
|
|
923
|
-
const { left } = node;
|
|
924
|
-
return left.type === AST_NODE_TYPES.MemberExpression && AST14.isThisExpression(left.object) && AST14.getPropertyName(left.property) === "state";
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
export { ComponentDetectionHint, ComponentFlag, ComponentPhaseRelevance, DEFAULT_COMPONENT_DETECTION_HINT, DEFAULT_JSX_DETECTION_HINT, JSXDetectionHint, findParentAttribute, getAttribute, getAttributeName, getAttributeValue, getComponentFlagFromInitPath, getComponentNameFromId, getElementType, getFunctionComponentId, getInstanceId, hasAnyAttribute, hasAttribute, hasEveryAttribute, hasNoneOrLooseComponentName, isAssignmentToThisState, isCaptureOwnerStack, isCaptureOwnerStackCall, isChildrenCount, isChildrenCountCall, isChildrenForEach, isChildrenForEachCall, isChildrenMap, isChildrenMapCall, isChildrenOfCreateElement, isChildrenOnly, isChildrenOnlyCall, isChildrenToArray, isChildrenToArrayCall, isClassComponent, isCloneElement, isCloneElementCall, isComponentDidCatch, isComponentDidMount, isComponentDidUpdate, isComponentName, isComponentNameLoose, isComponentWillMount, isComponentWillReceiveProps, isComponentWillUnmount, isComponentWillUpdate, isComponentWrapperCall, isComponentWrapperCallLoose, isCreateContext, isCreateContextCall, isCreateElement, isCreateElementCall, isCreateRef, isCreateRefCall, isDeclaredInRenderPropLoose, isDirectValueOfRenderPropertyLoose, isForwardRef, isForwardRefCall, isFragmentElement, isFunctionOfRender, isFunctionOfRenderMethod, isGetChildContext, isGetDefaultProps, isGetDerivedStateFromError, isGetDerivedStateFromProps, isGetInitialState, isGetSnapshotBeforeUpdate, isHostElement, isInitializedFromReact, isInstanceIdEqual, isInversePhase, isJsxLike, isJsxText, isKeyedElement, isLazy, isLazyCall, isMemo, isMemoCall, isPureComponent, isReactAPI, isReactAPICall, isReactHook, isReactHookCall, isReactHookCallWithName, isReactHookCallWithNameAlias, isReactHookCallWithNameLoose, isReactHookName, isRenderFunctionLoose, isRenderLike, isRenderMethodLike, isRenderPropLoose, isShouldComponentUpdate, isThisSetState, isUnsafeComponentWillMount, isUnsafeComponentWillReceiveProps, isUnsafeComponentWillUpdate, isUseActionStateCall, isUseCall, isUseCallbackCall, isUseContextCall, isUseDebugValueCall, isUseDeferredValueCall, isUseEffectCall, isUseEffectCallLoose, isUseFormStatusCall, isUseIdCall, isUseImperativeHandleCall, isUseInsertionEffectCall, isUseLayoutEffectCall, isUseMemoCall, isUseOptimisticCall, isUseReducerCall, isUseRefCall, isUseStateCall, isUseSyncExternalStoreCall, isUseTransitionCall, isValidComponentDefinition, stringifyJsx, useComponentCollector, useComponentCollectorLegacy, useHookCollector };
|