eslint-plugin-react-x 1.48.3 → 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.d.ts +32 -64
- package/dist/index.js +772 -917
- package/package.json +13 -21
- package/dist/index.d.mts +0 -325
- package/dist/index.mjs +0 -3696
package/dist/index.mjs
DELETED
|
@@ -1,3696 +0,0 @@
|
|
|
1
|
-
import { getDocsUrl, getSettingsFromContext, coerceSettings, DEFAULT_ESLINT_REACT_SETTINGS } from '@eslint-react/shared';
|
|
2
|
-
import * as ER25 from '@eslint-react/core';
|
|
3
|
-
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
4
|
-
import { JsxConfig, Reporter, Selector } from '@eslint-react/kit';
|
|
5
|
-
import { AST_NODE_TYPES } from '@typescript-eslint/types';
|
|
6
|
-
import * as VAR2 from '@eslint-react/var';
|
|
7
|
-
import { match, isMatching, P } from 'ts-pattern';
|
|
8
|
-
import ts, { JsxEmit } from 'typescript';
|
|
9
|
-
import * as AST8 from '@eslint-react/ast';
|
|
10
|
-
import { flow, getOrElseUpdate, constTrue, constFalse, _ } from '@eslint-react/eff';
|
|
11
|
-
import { compare } from 'compare-versions';
|
|
12
|
-
import { getConstrainedTypeAtLocation, isTypeReadonly } from '@typescript-eslint/type-utils';
|
|
13
|
-
import { unionTypeParts, isTypeFlagSet, isTrueLiteralType, isFalseLiteralType } from 'ts-api-utils';
|
|
14
|
-
import { getTypeImmutability, isUnknown, isImmutable, isReadonlyShallow, isReadonlyDeep } from 'is-immutable-type';
|
|
15
|
-
|
|
16
|
-
var __defProp = Object.defineProperty;
|
|
17
|
-
var __export = (target, all) => {
|
|
18
|
-
for (var name5 in all)
|
|
19
|
-
__defProp(target, name5, { get: all[name5], enumerable: true });
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
// src/configs/recommended.ts
|
|
23
|
-
var recommended_exports = {};
|
|
24
|
-
__export(recommended_exports, {
|
|
25
|
-
name: () => name,
|
|
26
|
-
rules: () => rules,
|
|
27
|
-
settings: () => settings
|
|
28
|
-
});
|
|
29
|
-
var name = "react-x/recommended";
|
|
30
|
-
var rules = {
|
|
31
|
-
"react-x/jsx-no-duplicate-props": "warn",
|
|
32
|
-
"react-x/jsx-uses-react": "warn",
|
|
33
|
-
"react-x/jsx-uses-vars": "warn",
|
|
34
|
-
"react-x/no-access-state-in-setstate": "error",
|
|
35
|
-
"react-x/no-array-index-key": "warn",
|
|
36
|
-
"react-x/no-children-count": "warn",
|
|
37
|
-
"react-x/no-children-for-each": "warn",
|
|
38
|
-
"react-x/no-children-map": "warn",
|
|
39
|
-
"react-x/no-children-only": "warn",
|
|
40
|
-
"react-x/no-children-to-array": "warn",
|
|
41
|
-
"react-x/no-clone-element": "warn",
|
|
42
|
-
"react-x/no-comment-textnodes": "warn",
|
|
43
|
-
"react-x/no-component-will-mount": "error",
|
|
44
|
-
"react-x/no-component-will-receive-props": "error",
|
|
45
|
-
"react-x/no-component-will-update": "error",
|
|
46
|
-
"react-x/no-context-provider": "warn",
|
|
47
|
-
"react-x/no-create-ref": "error",
|
|
48
|
-
"react-x/no-default-props": "error",
|
|
49
|
-
"react-x/no-direct-mutation-state": "error",
|
|
50
|
-
"react-x/no-duplicate-key": "warn",
|
|
51
|
-
"react-x/no-forward-ref": "warn",
|
|
52
|
-
"react-x/no-implicit-key": "warn",
|
|
53
|
-
"react-x/no-missing-key": "error",
|
|
54
|
-
"react-x/no-misused-capture-owner-stack": "error",
|
|
55
|
-
"react-x/no-nested-component-definitions": "error",
|
|
56
|
-
"react-x/no-nested-lazy-component-declarations": "warn",
|
|
57
|
-
"react-x/no-prop-types": "error",
|
|
58
|
-
"react-x/no-redundant-should-component-update": "error",
|
|
59
|
-
"react-x/no-set-state-in-component-did-mount": "warn",
|
|
60
|
-
"react-x/no-set-state-in-component-did-update": "warn",
|
|
61
|
-
"react-x/no-set-state-in-component-will-update": "warn",
|
|
62
|
-
"react-x/no-string-refs": "error",
|
|
63
|
-
"react-x/no-unsafe-component-will-mount": "warn",
|
|
64
|
-
"react-x/no-unsafe-component-will-receive-props": "warn",
|
|
65
|
-
"react-x/no-unsafe-component-will-update": "warn",
|
|
66
|
-
"react-x/no-unstable-context-value": "warn",
|
|
67
|
-
"react-x/no-unstable-default-props": "warn",
|
|
68
|
-
"react-x/no-unused-class-component-members": "warn",
|
|
69
|
-
"react-x/no-unused-state": "warn",
|
|
70
|
-
"react-x/no-use-context": "warn",
|
|
71
|
-
"react-x/no-useless-forward-ref": "warn"
|
|
72
|
-
};
|
|
73
|
-
var settings = {
|
|
74
|
-
"react-x": DEFAULT_ESLINT_REACT_SETTINGS
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
// src/configs/recommended-type-checked.ts
|
|
78
|
-
var recommended_type_checked_exports = {};
|
|
79
|
-
__export(recommended_type_checked_exports, {
|
|
80
|
-
name: () => name3,
|
|
81
|
-
rules: () => rules3,
|
|
82
|
-
settings: () => settings3
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
// src/configs/recommended-typescript.ts
|
|
86
|
-
var recommended_typescript_exports = {};
|
|
87
|
-
__export(recommended_typescript_exports, {
|
|
88
|
-
name: () => name2,
|
|
89
|
-
rules: () => rules2,
|
|
90
|
-
settings: () => settings2
|
|
91
|
-
});
|
|
92
|
-
var name2 = "react-x/recommended-typescript";
|
|
93
|
-
var rules2 = {
|
|
94
|
-
...rules,
|
|
95
|
-
"react-x/jsx-no-duplicate-props": "off",
|
|
96
|
-
"react-x/jsx-no-undef": "off",
|
|
97
|
-
"react-x/jsx-uses-react": "off",
|
|
98
|
-
"react-x/jsx-uses-vars": "off"
|
|
99
|
-
};
|
|
100
|
-
var settings2 = {
|
|
101
|
-
...settings
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
// src/configs/recommended-type-checked.ts
|
|
105
|
-
var name3 = "react-x/recommended-type-checked";
|
|
106
|
-
var rules3 = {
|
|
107
|
-
...rules2,
|
|
108
|
-
"react-x/no-leaked-conditional-rendering": "warn"
|
|
109
|
-
// "react-x/prefer-read-only-props": "warn",
|
|
110
|
-
};
|
|
111
|
-
var settings3 = {
|
|
112
|
-
...settings2
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
// package.json
|
|
116
|
-
var name4 = "eslint-plugin-react-x";
|
|
117
|
-
var version = "1.48.3";
|
|
118
|
-
var createRule = ESLintUtils.RuleCreator(getDocsUrl("x"));
|
|
119
|
-
|
|
120
|
-
// src/rules/avoid-shorthand-boolean.ts
|
|
121
|
-
var RULE_NAME = "avoid-shorthand-boolean";
|
|
122
|
-
var RULE_FEATURES = [];
|
|
123
|
-
var avoid_shorthand_boolean_default = createRule({
|
|
124
|
-
meta: {
|
|
125
|
-
type: "problem",
|
|
126
|
-
docs: {
|
|
127
|
-
description: "Enforces explicit boolean values for boolean attributes.",
|
|
128
|
-
[Symbol.for("rule_features")]: RULE_FEATURES
|
|
129
|
-
},
|
|
130
|
-
fixable: "code",
|
|
131
|
-
messages: {
|
|
132
|
-
avoidShorthandBoolean: "Avoid using shorthand boolean attribute '{{propName}}'. Use '{{propName}}={true}' instead."
|
|
133
|
-
},
|
|
134
|
-
schema: []
|
|
135
|
-
},
|
|
136
|
-
name: RULE_NAME,
|
|
137
|
-
create,
|
|
138
|
-
defaultOptions: []
|
|
139
|
-
});
|
|
140
|
-
function create(context) {
|
|
141
|
-
return {
|
|
142
|
-
JSXAttribute(node) {
|
|
143
|
-
if (node.value == null) {
|
|
144
|
-
context.report({
|
|
145
|
-
messageId: "avoidShorthandBoolean",
|
|
146
|
-
node,
|
|
147
|
-
data: {
|
|
148
|
-
propName: ER25.getAttributeName(context, node)
|
|
149
|
-
},
|
|
150
|
-
fix: (fixer) => fixer.insertTextAfter(node.name, `={true}`)
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
var RULE_NAME2 = "avoid-shorthand-fragment";
|
|
157
|
-
var RULE_FEATURES2 = [];
|
|
158
|
-
var avoid_shorthand_fragment_default = createRule({
|
|
159
|
-
meta: {
|
|
160
|
-
type: "problem",
|
|
161
|
-
docs: {
|
|
162
|
-
description: "Enforces explicit `<Fragment>` components instead of the shorthand `<>` or `</>` syntax.",
|
|
163
|
-
[Symbol.for("rule_features")]: RULE_FEATURES2
|
|
164
|
-
},
|
|
165
|
-
messages: {
|
|
166
|
-
avoidShorthandFragment: "Avoid using shorthand fragment syntax. Use '{{jsxFragmentFactory}}' component instead."
|
|
167
|
-
},
|
|
168
|
-
schema: []
|
|
169
|
-
},
|
|
170
|
-
name: RULE_NAME2,
|
|
171
|
-
create: create2,
|
|
172
|
-
defaultOptions: []
|
|
173
|
-
});
|
|
174
|
-
function create2(context) {
|
|
175
|
-
const jsxConfigFromContext = JsxConfig.getFromContext(context);
|
|
176
|
-
const jsxConfigFromAnnotation = JsxConfig.getFromAnnotation(context);
|
|
177
|
-
const jsxConfig = {
|
|
178
|
-
...jsxConfigFromContext,
|
|
179
|
-
...jsxConfigFromAnnotation
|
|
180
|
-
};
|
|
181
|
-
return {
|
|
182
|
-
JSXFragment(node) {
|
|
183
|
-
context.report({
|
|
184
|
-
messageId: "avoidShorthandFragment",
|
|
185
|
-
node,
|
|
186
|
-
data: {
|
|
187
|
-
jsxFragmentFactory: jsxConfig.jsxFragmentFactory
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
var RULE_NAME3 = "jsx-no-duplicate-props";
|
|
194
|
-
var RULE_FEATURES3 = [];
|
|
195
|
-
var jsx_no_duplicate_props_default = createRule({
|
|
196
|
-
meta: {
|
|
197
|
-
type: "problem",
|
|
198
|
-
docs: {
|
|
199
|
-
description: "Disallow duplicate props in JSX elements.",
|
|
200
|
-
[Symbol.for("rule_features")]: RULE_FEATURES3
|
|
201
|
-
},
|
|
202
|
-
messages: {
|
|
203
|
-
jsxNoDuplicateProps: "This JSX property is assigned multiple times."
|
|
204
|
-
},
|
|
205
|
-
schema: []
|
|
206
|
-
},
|
|
207
|
-
name: RULE_NAME3,
|
|
208
|
-
create: create3,
|
|
209
|
-
defaultOptions: []
|
|
210
|
-
});
|
|
211
|
-
function create3(context) {
|
|
212
|
-
return {
|
|
213
|
-
JSXOpeningElement(node) {
|
|
214
|
-
const props = [];
|
|
215
|
-
for (const attr of node.attributes) {
|
|
216
|
-
if (attr.type === AST_NODE_TYPES.JSXSpreadAttribute) {
|
|
217
|
-
continue;
|
|
218
|
-
}
|
|
219
|
-
const name5 = attr.name.name;
|
|
220
|
-
if (typeof name5 !== "string") {
|
|
221
|
-
continue;
|
|
222
|
-
}
|
|
223
|
-
if (!props.includes(name5)) {
|
|
224
|
-
props.push(name5);
|
|
225
|
-
continue;
|
|
226
|
-
}
|
|
227
|
-
context.report({
|
|
228
|
-
messageId: "jsxNoDuplicateProps",
|
|
229
|
-
node: attr
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
var RULE_NAME4 = "jsx-no-undef";
|
|
236
|
-
var RULE_FEATURES4 = [];
|
|
237
|
-
var jsx_no_undef_default = createRule({
|
|
238
|
-
meta: {
|
|
239
|
-
type: "problem",
|
|
240
|
-
docs: {
|
|
241
|
-
description: "Disallow undefined variables in JSX.",
|
|
242
|
-
[Symbol.for("rule_features")]: RULE_FEATURES4
|
|
243
|
-
},
|
|
244
|
-
messages: {
|
|
245
|
-
jsxNoUndef: "JSX variable '{{name}}' is not defined."
|
|
246
|
-
},
|
|
247
|
-
schema: []
|
|
248
|
-
},
|
|
249
|
-
name: RULE_NAME4,
|
|
250
|
-
create: create4,
|
|
251
|
-
defaultOptions: []
|
|
252
|
-
});
|
|
253
|
-
function create4(context) {
|
|
254
|
-
return {
|
|
255
|
-
JSXOpeningElement(node) {
|
|
256
|
-
const name5 = match(node.name).with({ type: AST_NODE_TYPES.JSXIdentifier }, (n) => n.name).with({ type: AST_NODE_TYPES.JSXMemberExpression, object: { type: AST_NODE_TYPES.JSXIdentifier } }, (n) => n.object.name).otherwise(() => null);
|
|
257
|
-
if (name5 == null) return;
|
|
258
|
-
if (name5 === "this") return;
|
|
259
|
-
if (/^[a-z]/u.test(name5)) return;
|
|
260
|
-
if (VAR2.findVariable(name5, context.sourceCode.getScope(node)) == null) {
|
|
261
|
-
context.report({
|
|
262
|
-
messageId: "jsxNoUndef",
|
|
263
|
-
node,
|
|
264
|
-
data: {
|
|
265
|
-
name: name5
|
|
266
|
-
}
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
var RULE_NAME5 = "jsx-uses-react";
|
|
273
|
-
var RULE_FEATURES5 = [];
|
|
274
|
-
var jsx_uses_react_default = createRule({
|
|
275
|
-
meta: {
|
|
276
|
-
type: "problem",
|
|
277
|
-
docs: {
|
|
278
|
-
description: "Marks React variables as used when JSX is used.",
|
|
279
|
-
[Symbol.for("rule_features")]: RULE_FEATURES5
|
|
280
|
-
},
|
|
281
|
-
messages: {
|
|
282
|
-
jsxUsesReact: "Marked {{name}} as used."
|
|
283
|
-
},
|
|
284
|
-
schema: []
|
|
285
|
-
},
|
|
286
|
-
name: RULE_NAME5,
|
|
287
|
-
create: create5,
|
|
288
|
-
defaultOptions: []
|
|
289
|
-
});
|
|
290
|
-
function create5(context) {
|
|
291
|
-
const jsxConfig = {
|
|
292
|
-
...JsxConfig.getFromContext(context),
|
|
293
|
-
...JsxConfig.getFromAnnotation(context)
|
|
294
|
-
};
|
|
295
|
-
const { jsx, jsxFactory, jsxFragmentFactory } = jsxConfig;
|
|
296
|
-
if (jsx === JsxEmit.ReactJSX || jsx === JsxEmit.ReactJSXDev) return {};
|
|
297
|
-
function handleJsxElement(node) {
|
|
298
|
-
context.sourceCode.markVariableAsUsed(jsxFactory, node);
|
|
299
|
-
debugReport(context, node, jsxFactory);
|
|
300
|
-
}
|
|
301
|
-
function handleJsxFragment(node) {
|
|
302
|
-
context.sourceCode.markVariableAsUsed(jsxFragmentFactory, node);
|
|
303
|
-
debugReport(context, node, jsxFragmentFactory);
|
|
304
|
-
}
|
|
305
|
-
return {
|
|
306
|
-
JSXFragment: handleJsxFragment,
|
|
307
|
-
JSXOpeningElement: handleJsxElement,
|
|
308
|
-
JSXOpeningFragment: handleJsxElement
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
function debugReport(context, node, name5) {
|
|
312
|
-
if (process.env["ESLINT_REACT_DEBUG"] !== "1") return;
|
|
313
|
-
context.report({
|
|
314
|
-
messageId: "jsxUsesReact",
|
|
315
|
-
node,
|
|
316
|
-
data: { name: name5 }
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
var RULE_NAME6 = "jsx-uses-vars";
|
|
320
|
-
var RULE_FEATURES6 = [];
|
|
321
|
-
var jsx_uses_vars_default = createRule({
|
|
322
|
-
meta: {
|
|
323
|
-
type: "problem",
|
|
324
|
-
docs: {
|
|
325
|
-
description: "Marks variables used in JSX elements as used.",
|
|
326
|
-
[Symbol.for("rule_features")]: RULE_FEATURES6
|
|
327
|
-
},
|
|
328
|
-
messages: {
|
|
329
|
-
jsxUsesVars: ""
|
|
330
|
-
},
|
|
331
|
-
schema: []
|
|
332
|
-
},
|
|
333
|
-
name: RULE_NAME6,
|
|
334
|
-
create: create6,
|
|
335
|
-
defaultOptions: []
|
|
336
|
-
});
|
|
337
|
-
function create6(context) {
|
|
338
|
-
return {
|
|
339
|
-
JSXOpeningElement(node) {
|
|
340
|
-
switch (node.name.type) {
|
|
341
|
-
case AST_NODE_TYPES.JSXIdentifier: {
|
|
342
|
-
if (/^[a-z]/u.test(node.name.name)) {
|
|
343
|
-
return;
|
|
344
|
-
}
|
|
345
|
-
context.sourceCode.markVariableAsUsed(node.name.name, node);
|
|
346
|
-
break;
|
|
347
|
-
}
|
|
348
|
-
case AST_NODE_TYPES.JSXMemberExpression: {
|
|
349
|
-
const { object } = node.name;
|
|
350
|
-
if (object.type === AST_NODE_TYPES.JSXIdentifier) {
|
|
351
|
-
context.sourceCode.markVariableAsUsed(object.name, node);
|
|
352
|
-
}
|
|
353
|
-
break;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
};
|
|
358
|
-
}
|
|
359
|
-
var RULE_NAME7 = "no-access-state-in-setstate";
|
|
360
|
-
var RULE_FEATURES7 = [];
|
|
361
|
-
function isKeyLiteral(node, key) {
|
|
362
|
-
return match(key).with({ type: AST_NODE_TYPES.Literal }, constTrue).with({ type: AST_NODE_TYPES.TemplateLiteral, expressions: [] }, constTrue).with({ type: AST_NODE_TYPES.Identifier }, () => !node.computed).otherwise(constFalse);
|
|
363
|
-
}
|
|
364
|
-
var no_access_state_in_setstate_default = createRule({
|
|
365
|
-
meta: {
|
|
366
|
-
type: "problem",
|
|
367
|
-
docs: {
|
|
368
|
-
description: "Disallow accessing `this.state` inside `setState` calls.",
|
|
369
|
-
[Symbol.for("rule_features")]: RULE_FEATURES7
|
|
370
|
-
},
|
|
371
|
-
messages: {
|
|
372
|
-
noAccessStateInSetstate: "Do not access 'this.state' within 'setState'. Use the update function instead."
|
|
373
|
-
},
|
|
374
|
-
schema: []
|
|
375
|
-
},
|
|
376
|
-
name: RULE_NAME7,
|
|
377
|
-
create: create7,
|
|
378
|
-
defaultOptions: []
|
|
379
|
-
});
|
|
380
|
-
function create7(context) {
|
|
381
|
-
if (!context.sourceCode.text.includes("setState")) {
|
|
382
|
-
return {};
|
|
383
|
-
}
|
|
384
|
-
const classEntries = [];
|
|
385
|
-
const methodEntries = [];
|
|
386
|
-
const setStateEntries = [];
|
|
387
|
-
return {
|
|
388
|
-
CallExpression(node) {
|
|
389
|
-
if (!ER25.isThisSetState(node)) {
|
|
390
|
-
return;
|
|
391
|
-
}
|
|
392
|
-
setStateEntries.push([node, false]);
|
|
393
|
-
},
|
|
394
|
-
"CallExpression:exit"(node) {
|
|
395
|
-
if (!ER25.isThisSetState(node)) {
|
|
396
|
-
return;
|
|
397
|
-
}
|
|
398
|
-
setStateEntries.pop();
|
|
399
|
-
},
|
|
400
|
-
ClassDeclaration(node) {
|
|
401
|
-
classEntries.push([node, ER25.isClassComponent(node)]);
|
|
402
|
-
},
|
|
403
|
-
"ClassDeclaration:exit"() {
|
|
404
|
-
classEntries.pop();
|
|
405
|
-
},
|
|
406
|
-
ClassExpression(node) {
|
|
407
|
-
classEntries.push([node, ER25.isClassComponent(node)]);
|
|
408
|
-
},
|
|
409
|
-
"ClassExpression:exit"() {
|
|
410
|
-
classEntries.pop();
|
|
411
|
-
},
|
|
412
|
-
MemberExpression(node) {
|
|
413
|
-
if (!AST8.isThisExpression(node.object)) {
|
|
414
|
-
return;
|
|
415
|
-
}
|
|
416
|
-
const [currClass, isComponent = false] = classEntries.at(-1) ?? [];
|
|
417
|
-
if (currClass == null || !isComponent) {
|
|
418
|
-
return;
|
|
419
|
-
}
|
|
420
|
-
const [currMethod, isStatic = false] = methodEntries.at(-1) ?? [];
|
|
421
|
-
if (currMethod == null || isStatic) {
|
|
422
|
-
return;
|
|
423
|
-
}
|
|
424
|
-
const [setState, hasThisState = false] = setStateEntries.at(-1) ?? [];
|
|
425
|
-
if (setState == null || hasThisState) {
|
|
426
|
-
return;
|
|
427
|
-
}
|
|
428
|
-
if (AST8.getPropertyName(node.property) !== "state") {
|
|
429
|
-
return;
|
|
430
|
-
}
|
|
431
|
-
context.report({ messageId: "noAccessStateInSetstate", node });
|
|
432
|
-
},
|
|
433
|
-
MethodDefinition(node) {
|
|
434
|
-
methodEntries.push([node, node.static]);
|
|
435
|
-
},
|
|
436
|
-
"MethodDefinition:exit"() {
|
|
437
|
-
methodEntries.pop();
|
|
438
|
-
},
|
|
439
|
-
PropertyDefinition(node) {
|
|
440
|
-
methodEntries.push([node, node.static]);
|
|
441
|
-
},
|
|
442
|
-
"PropertyDefinition:exit"() {
|
|
443
|
-
methodEntries.pop();
|
|
444
|
-
},
|
|
445
|
-
VariableDeclarator(node) {
|
|
446
|
-
const [currClass, isComponent = false] = classEntries.at(-1) ?? [];
|
|
447
|
-
if (currClass == null || !isComponent) {
|
|
448
|
-
return;
|
|
449
|
-
}
|
|
450
|
-
const [currMethod, isStatic = false] = methodEntries.at(-1) ?? [];
|
|
451
|
-
if (currMethod == null || isStatic) {
|
|
452
|
-
return;
|
|
453
|
-
}
|
|
454
|
-
const [setState, hasThisState = false] = setStateEntries.at(-1) ?? [];
|
|
455
|
-
if (setState == null || hasThisState) {
|
|
456
|
-
return;
|
|
457
|
-
}
|
|
458
|
-
if (node.init == null || !AST8.isThisExpression(node.init) || node.id.type !== AST_NODE_TYPES.ObjectPattern) {
|
|
459
|
-
return;
|
|
460
|
-
}
|
|
461
|
-
const hasState = node.id.properties.some(
|
|
462
|
-
(prop) => prop.type === AST_NODE_TYPES.Property && isKeyLiteral(prop, prop.key) && AST8.getPropertyName(prop.key) === "state"
|
|
463
|
-
);
|
|
464
|
-
if (!hasState) {
|
|
465
|
-
return;
|
|
466
|
-
}
|
|
467
|
-
context.report({ messageId: "noAccessStateInSetstate", node });
|
|
468
|
-
}
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
|
-
var RULE_NAME8 = "no-array-index-key";
|
|
472
|
-
var RULE_FEATURES8 = [];
|
|
473
|
-
var reactChildrenMethod = ["forEach", "map"];
|
|
474
|
-
function isReactChildrenMethod(name5) {
|
|
475
|
-
return reactChildrenMethod.some((method) => method === name5);
|
|
476
|
-
}
|
|
477
|
-
function isUsingReactChildren(context, node) {
|
|
478
|
-
const { importSource = "react" } = coerceSettings(context.settings);
|
|
479
|
-
const { callee } = node;
|
|
480
|
-
if (!("property" in callee) || !("object" in callee) || !("name" in callee.property)) {
|
|
481
|
-
return false;
|
|
482
|
-
}
|
|
483
|
-
if (!isReactChildrenMethod(callee.property.name)) {
|
|
484
|
-
return false;
|
|
485
|
-
}
|
|
486
|
-
const initialScope = context.sourceCode.getScope(node);
|
|
487
|
-
if (callee.object.type === AST_NODE_TYPES.Identifier && callee.object.name === "Children") {
|
|
488
|
-
return true;
|
|
489
|
-
}
|
|
490
|
-
if (callee.object.type === AST_NODE_TYPES.MemberExpression && "name" in callee.object.object) {
|
|
491
|
-
return ER25.isInitializedFromReact(callee.object.object.name, importSource, initialScope);
|
|
492
|
-
}
|
|
493
|
-
return false;
|
|
494
|
-
}
|
|
495
|
-
function getMapIndexParamName(context, node) {
|
|
496
|
-
const { callee } = node;
|
|
497
|
-
if (callee.type !== AST_NODE_TYPES.MemberExpression) {
|
|
498
|
-
return _;
|
|
499
|
-
}
|
|
500
|
-
if (callee.property.type !== AST_NODE_TYPES.Identifier) {
|
|
501
|
-
return _;
|
|
502
|
-
}
|
|
503
|
-
const { name: name5 } = callee.property;
|
|
504
|
-
const indexPosition = AST8.getArrayMethodCallbackIndexParamPosition(name5);
|
|
505
|
-
if (indexPosition === -1) {
|
|
506
|
-
return _;
|
|
507
|
-
}
|
|
508
|
-
const callbackArg = node.arguments[isUsingReactChildren(context, node) ? 1 : 0];
|
|
509
|
-
if (callbackArg == null) {
|
|
510
|
-
return _;
|
|
511
|
-
}
|
|
512
|
-
if (!AST8.isOneOf([AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression])(callbackArg)) {
|
|
513
|
-
return _;
|
|
514
|
-
}
|
|
515
|
-
const { params } = callbackArg;
|
|
516
|
-
if (params.length < indexPosition + 1) {
|
|
517
|
-
return _;
|
|
518
|
-
}
|
|
519
|
-
const param = params.at(indexPosition);
|
|
520
|
-
return param != null && "name" in param ? param.name : _;
|
|
521
|
-
}
|
|
522
|
-
function getIdentifiersFromBinaryExpression(side) {
|
|
523
|
-
if (side.type === AST_NODE_TYPES.Identifier) {
|
|
524
|
-
return [side];
|
|
525
|
-
}
|
|
526
|
-
if (side.type === AST_NODE_TYPES.BinaryExpression) {
|
|
527
|
-
return [
|
|
528
|
-
...getIdentifiersFromBinaryExpression(side.left),
|
|
529
|
-
...getIdentifiersFromBinaryExpression(side.right)
|
|
530
|
-
];
|
|
531
|
-
}
|
|
532
|
-
return [];
|
|
533
|
-
}
|
|
534
|
-
var no_array_index_key_default = createRule({
|
|
535
|
-
meta: {
|
|
536
|
-
type: "problem",
|
|
537
|
-
docs: {
|
|
538
|
-
description: "Disallow an item's index in the array as its key.",
|
|
539
|
-
[Symbol.for("rule_features")]: RULE_FEATURES8
|
|
540
|
-
},
|
|
541
|
-
messages: {
|
|
542
|
-
noArrayIndexKey: "Do not use item index in the array as its key."
|
|
543
|
-
},
|
|
544
|
-
schema: []
|
|
545
|
-
},
|
|
546
|
-
name: RULE_NAME8,
|
|
547
|
-
create: create8,
|
|
548
|
-
defaultOptions: []
|
|
549
|
-
});
|
|
550
|
-
function create8(context) {
|
|
551
|
-
const report = Reporter.make(context);
|
|
552
|
-
const indexParamNames = [];
|
|
553
|
-
function isArrayIndex(node) {
|
|
554
|
-
return node.type === AST_NODE_TYPES.Identifier && indexParamNames.some((name5) => name5 != null && name5 === node.name);
|
|
555
|
-
}
|
|
556
|
-
function isCreateOrCloneElementCall(node) {
|
|
557
|
-
return ER25.isCreateElementCall(context, node) || ER25.isCloneElementCall(context, node);
|
|
558
|
-
}
|
|
559
|
-
function getReportDescriptors(node) {
|
|
560
|
-
switch (node.type) {
|
|
561
|
-
// key={bar}
|
|
562
|
-
case AST_NODE_TYPES.Identifier: {
|
|
563
|
-
if (indexParamNames.some((name5) => name5 != null && name5 === node.name)) {
|
|
564
|
-
return [{
|
|
565
|
-
messageId: "noArrayIndexKey",
|
|
566
|
-
node
|
|
567
|
-
}];
|
|
568
|
-
}
|
|
569
|
-
return [];
|
|
570
|
-
}
|
|
571
|
-
// key={`foo-${bar}`} or key={'foo' + bar}
|
|
572
|
-
case AST_NODE_TYPES.TemplateLiteral:
|
|
573
|
-
case AST_NODE_TYPES.BinaryExpression: {
|
|
574
|
-
const descriptors = [];
|
|
575
|
-
const expressions = node.type === AST_NODE_TYPES.TemplateLiteral ? node.expressions : getIdentifiersFromBinaryExpression(node);
|
|
576
|
-
for (const expression of expressions) {
|
|
577
|
-
if (isArrayIndex(expression)) {
|
|
578
|
-
descriptors.push({
|
|
579
|
-
messageId: "noArrayIndexKey",
|
|
580
|
-
node: expression
|
|
581
|
-
});
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
return descriptors;
|
|
585
|
-
}
|
|
586
|
-
// key={bar.toString()} or key={String(bar)}
|
|
587
|
-
case AST_NODE_TYPES.CallExpression: {
|
|
588
|
-
switch (true) {
|
|
589
|
-
// key={bar.toString()}
|
|
590
|
-
case (node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.type === AST_NODE_TYPES.Identifier && node.callee.property.name === "toString" && isArrayIndex(node.callee.object)): {
|
|
591
|
-
return [{
|
|
592
|
-
messageId: "noArrayIndexKey",
|
|
593
|
-
node: node.callee.object
|
|
594
|
-
}];
|
|
595
|
-
}
|
|
596
|
-
// key={String(bar)}
|
|
597
|
-
case (node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === "String" && node.arguments[0] != null && isArrayIndex(node.arguments[0])): {
|
|
598
|
-
return [{
|
|
599
|
-
messageId: "noArrayIndexKey",
|
|
600
|
-
node: node.arguments[0]
|
|
601
|
-
}];
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
return [];
|
|
607
|
-
}
|
|
608
|
-
return {
|
|
609
|
-
CallExpression(node) {
|
|
610
|
-
indexParamNames.push(getMapIndexParamName(context, node));
|
|
611
|
-
if (node.arguments.length === 0) {
|
|
612
|
-
return;
|
|
613
|
-
}
|
|
614
|
-
if (!isCreateOrCloneElementCall(node)) {
|
|
615
|
-
return;
|
|
616
|
-
}
|
|
617
|
-
const [, props] = node.arguments;
|
|
618
|
-
if (props?.type !== AST_NODE_TYPES.ObjectExpression) {
|
|
619
|
-
return;
|
|
620
|
-
}
|
|
621
|
-
for (const prop of props.properties) {
|
|
622
|
-
if (!isMatching({ key: { name: "key" } })(prop)) {
|
|
623
|
-
continue;
|
|
624
|
-
}
|
|
625
|
-
if (!("value" in prop)) {
|
|
626
|
-
continue;
|
|
627
|
-
}
|
|
628
|
-
for (const descriptor of getReportDescriptors(prop.value)) {
|
|
629
|
-
report.send(descriptor);
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
},
|
|
633
|
-
"CallExpression:exit"() {
|
|
634
|
-
indexParamNames.pop();
|
|
635
|
-
},
|
|
636
|
-
JSXAttribute(node) {
|
|
637
|
-
if (node.name.name !== "key") {
|
|
638
|
-
return;
|
|
639
|
-
}
|
|
640
|
-
if (indexParamNames.length === 0) {
|
|
641
|
-
return;
|
|
642
|
-
}
|
|
643
|
-
if (node.value?.type !== AST_NODE_TYPES.JSXExpressionContainer) {
|
|
644
|
-
return;
|
|
645
|
-
}
|
|
646
|
-
for (const descriptor of getReportDescriptors(node.value.expression)) {
|
|
647
|
-
report.send(descriptor);
|
|
648
|
-
}
|
|
649
|
-
}
|
|
650
|
-
};
|
|
651
|
-
}
|
|
652
|
-
var RULE_NAME9 = "no-children-count";
|
|
653
|
-
var RULE_FEATURES9 = [];
|
|
654
|
-
var no_children_count_default = createRule({
|
|
655
|
-
meta: {
|
|
656
|
-
type: "problem",
|
|
657
|
-
docs: {
|
|
658
|
-
description: "Disallow `Children.count`.",
|
|
659
|
-
[Symbol.for("rule_features")]: RULE_FEATURES9
|
|
660
|
-
},
|
|
661
|
-
messages: {
|
|
662
|
-
noChildrenCount: "Using 'Children.count' is uncommon and can lead to fragile code. Use alternatives instead."
|
|
663
|
-
},
|
|
664
|
-
schema: []
|
|
665
|
-
},
|
|
666
|
-
name: RULE_NAME9,
|
|
667
|
-
create: create9,
|
|
668
|
-
defaultOptions: []
|
|
669
|
-
});
|
|
670
|
-
function create9(context) {
|
|
671
|
-
return {
|
|
672
|
-
MemberExpression(node) {
|
|
673
|
-
if (ER25.isChildrenCount(context, node)) {
|
|
674
|
-
context.report({
|
|
675
|
-
messageId: "noChildrenCount",
|
|
676
|
-
node: node.property
|
|
677
|
-
});
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
};
|
|
681
|
-
}
|
|
682
|
-
var RULE_NAME10 = "no-children-for-each";
|
|
683
|
-
var RULE_FEATURES10 = [];
|
|
684
|
-
var no_children_for_each_default = createRule({
|
|
685
|
-
meta: {
|
|
686
|
-
type: "problem",
|
|
687
|
-
docs: {
|
|
688
|
-
description: "Disallow 'Children.forEach'.",
|
|
689
|
-
[Symbol.for("rule_features")]: RULE_FEATURES10
|
|
690
|
-
},
|
|
691
|
-
messages: {
|
|
692
|
-
noChildrenForEach: "Using 'Children.forEach' is uncommon and can lead to fragile code. Use alternatives instead."
|
|
693
|
-
},
|
|
694
|
-
schema: []
|
|
695
|
-
},
|
|
696
|
-
name: RULE_NAME10,
|
|
697
|
-
create: create10,
|
|
698
|
-
defaultOptions: []
|
|
699
|
-
});
|
|
700
|
-
function create10(context) {
|
|
701
|
-
return {
|
|
702
|
-
MemberExpression(node) {
|
|
703
|
-
if (ER25.isChildrenForEach(context, node)) {
|
|
704
|
-
context.report({
|
|
705
|
-
messageId: "noChildrenForEach",
|
|
706
|
-
node: node.property
|
|
707
|
-
});
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
};
|
|
711
|
-
}
|
|
712
|
-
var RULE_NAME11 = "no-children-map";
|
|
713
|
-
var RULE_FEATURES11 = [];
|
|
714
|
-
var no_children_map_default = createRule({
|
|
715
|
-
meta: {
|
|
716
|
-
type: "problem",
|
|
717
|
-
docs: {
|
|
718
|
-
description: "Disallow `Children.map`.",
|
|
719
|
-
[Symbol.for("rule_features")]: RULE_FEATURES11
|
|
720
|
-
},
|
|
721
|
-
messages: {
|
|
722
|
-
noChildrenMap: "Using 'Children.map' is uncommon and can lead to fragile code. Use alternatives instead."
|
|
723
|
-
},
|
|
724
|
-
schema: []
|
|
725
|
-
},
|
|
726
|
-
name: RULE_NAME11,
|
|
727
|
-
create: create11,
|
|
728
|
-
defaultOptions: []
|
|
729
|
-
});
|
|
730
|
-
function create11(context) {
|
|
731
|
-
return {
|
|
732
|
-
MemberExpression(node) {
|
|
733
|
-
if (ER25.isChildrenMap(context, node)) {
|
|
734
|
-
context.report({
|
|
735
|
-
messageId: "noChildrenMap",
|
|
736
|
-
node: node.property
|
|
737
|
-
});
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
};
|
|
741
|
-
}
|
|
742
|
-
var RULE_NAME12 = "no-children-only";
|
|
743
|
-
var RULE_FEATURES12 = [];
|
|
744
|
-
var no_children_only_default = createRule({
|
|
745
|
-
meta: {
|
|
746
|
-
type: "problem",
|
|
747
|
-
docs: {
|
|
748
|
-
description: "Disallow `Children.only`.",
|
|
749
|
-
[Symbol.for("rule_features")]: RULE_FEATURES12
|
|
750
|
-
},
|
|
751
|
-
messages: {
|
|
752
|
-
noChildrenOnly: "Using 'Children.only' is uncommon and can lead to fragile code. Use alternatives instead."
|
|
753
|
-
},
|
|
754
|
-
schema: []
|
|
755
|
-
},
|
|
756
|
-
name: RULE_NAME12,
|
|
757
|
-
create: create12,
|
|
758
|
-
defaultOptions: []
|
|
759
|
-
});
|
|
760
|
-
function create12(context) {
|
|
761
|
-
return {
|
|
762
|
-
MemberExpression(node) {
|
|
763
|
-
if (ER25.isChildrenOnly(context, node)) {
|
|
764
|
-
context.report({
|
|
765
|
-
messageId: "noChildrenOnly",
|
|
766
|
-
node: node.property
|
|
767
|
-
});
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
};
|
|
771
|
-
}
|
|
772
|
-
var RULE_NAME13 = "no-children-prop";
|
|
773
|
-
var RULE_FEATURES13 = [];
|
|
774
|
-
var no_children_prop_default = createRule({
|
|
775
|
-
meta: {
|
|
776
|
-
type: "problem",
|
|
777
|
-
docs: {
|
|
778
|
-
description: "Disallow passing `children` as a prop.",
|
|
779
|
-
[Symbol.for("rule_features")]: RULE_FEATURES13
|
|
780
|
-
},
|
|
781
|
-
messages: {
|
|
782
|
-
noChildrenProp: "Do not pass 'children' as props."
|
|
783
|
-
},
|
|
784
|
-
schema: []
|
|
785
|
-
},
|
|
786
|
-
name: RULE_NAME13,
|
|
787
|
-
create: create13,
|
|
788
|
-
defaultOptions: []
|
|
789
|
-
});
|
|
790
|
-
function create13(context) {
|
|
791
|
-
return {
|
|
792
|
-
JSXElement(node) {
|
|
793
|
-
const attributes = node.openingElement.attributes;
|
|
794
|
-
const childrenProp = ER25.getAttribute(context, "children", attributes, context.sourceCode.getScope(node));
|
|
795
|
-
if (childrenProp != null) {
|
|
796
|
-
context.report({
|
|
797
|
-
messageId: "noChildrenProp",
|
|
798
|
-
node: childrenProp
|
|
799
|
-
});
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
};
|
|
803
|
-
}
|
|
804
|
-
var RULE_NAME14 = "no-children-to-array";
|
|
805
|
-
var RULE_FEATURES14 = [];
|
|
806
|
-
var no_children_to_array_default = createRule({
|
|
807
|
-
meta: {
|
|
808
|
-
type: "problem",
|
|
809
|
-
docs: {
|
|
810
|
-
description: "Disallow `Children.toArray`.",
|
|
811
|
-
[Symbol.for("rule_features")]: RULE_FEATURES14
|
|
812
|
-
},
|
|
813
|
-
messages: {
|
|
814
|
-
noChildrenToArray: "Using 'Children.toArray' is uncommon and can lead to fragile code. Use alternatives instead."
|
|
815
|
-
},
|
|
816
|
-
schema: []
|
|
817
|
-
},
|
|
818
|
-
name: RULE_NAME14,
|
|
819
|
-
create: create14,
|
|
820
|
-
defaultOptions: []
|
|
821
|
-
});
|
|
822
|
-
function create14(context) {
|
|
823
|
-
return {
|
|
824
|
-
MemberExpression(node) {
|
|
825
|
-
if (ER25.isChildrenToArray(context, node)) {
|
|
826
|
-
context.report({
|
|
827
|
-
messageId: "noChildrenToArray",
|
|
828
|
-
node: node.property
|
|
829
|
-
});
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
};
|
|
833
|
-
}
|
|
834
|
-
var RULE_NAME15 = "no-class-component";
|
|
835
|
-
var RULE_FEATURES15 = [];
|
|
836
|
-
var no_class_component_default = createRule({
|
|
837
|
-
meta: {
|
|
838
|
-
type: "problem",
|
|
839
|
-
docs: {
|
|
840
|
-
description: "Disallow class components except for error boundaries.",
|
|
841
|
-
[Symbol.for("rule_features")]: RULE_FEATURES15
|
|
842
|
-
},
|
|
843
|
-
messages: {
|
|
844
|
-
noClassComponent: "Avoid using class components. Use function components instead."
|
|
845
|
-
},
|
|
846
|
-
schema: []
|
|
847
|
-
},
|
|
848
|
-
name: RULE_NAME15,
|
|
849
|
-
create: create15,
|
|
850
|
-
defaultOptions: []
|
|
851
|
-
});
|
|
852
|
-
function create15(context) {
|
|
853
|
-
if (!context.sourceCode.text.includes("Component")) return {};
|
|
854
|
-
const { ctx, listeners } = ER25.useComponentCollectorLegacy();
|
|
855
|
-
return {
|
|
856
|
-
...listeners,
|
|
857
|
-
"Program:exit"(program) {
|
|
858
|
-
const components = ctx.getAllComponents(program);
|
|
859
|
-
for (const { name: name5 = "anonymous", node: component } of components.values()) {
|
|
860
|
-
if (component.body.body.some((m) => ER25.isComponentDidCatch(m) || ER25.isGetDerivedStateFromError(m))) {
|
|
861
|
-
continue;
|
|
862
|
-
}
|
|
863
|
-
context.report({
|
|
864
|
-
messageId: "noClassComponent",
|
|
865
|
-
node: component,
|
|
866
|
-
data: {
|
|
867
|
-
name: name5
|
|
868
|
-
}
|
|
869
|
-
});
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
};
|
|
873
|
-
}
|
|
874
|
-
var RULE_NAME16 = "no-clone-element";
|
|
875
|
-
var RULE_FEATURES16 = [];
|
|
876
|
-
var no_clone_element_default = createRule({
|
|
877
|
-
meta: {
|
|
878
|
-
type: "problem",
|
|
879
|
-
docs: {
|
|
880
|
-
description: "Disallow `cloneElement`.",
|
|
881
|
-
[Symbol.for("rule_features")]: RULE_FEATURES16
|
|
882
|
-
},
|
|
883
|
-
messages: {
|
|
884
|
-
noCloneElement: "Using 'cloneElement' is uncommon and can lead to fragile code. Use alternatives instead."
|
|
885
|
-
},
|
|
886
|
-
schema: []
|
|
887
|
-
},
|
|
888
|
-
name: RULE_NAME16,
|
|
889
|
-
create: create16,
|
|
890
|
-
defaultOptions: []
|
|
891
|
-
});
|
|
892
|
-
function create16(context) {
|
|
893
|
-
return {
|
|
894
|
-
CallExpression(node) {
|
|
895
|
-
if (ER25.isCloneElementCall(context, node)) {
|
|
896
|
-
context.report({
|
|
897
|
-
messageId: "noCloneElement",
|
|
898
|
-
node
|
|
899
|
-
});
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
};
|
|
903
|
-
}
|
|
904
|
-
var RULE_NAME17 = "no-comment-textnodes";
|
|
905
|
-
var RULE_FEATURES17 = [];
|
|
906
|
-
var no_comment_textnodes_default = createRule({
|
|
907
|
-
meta: {
|
|
908
|
-
type: "problem",
|
|
909
|
-
docs: {
|
|
910
|
-
description: "Prevents comments from being inserted as text nodes.",
|
|
911
|
-
[Symbol.for("rule_features")]: RULE_FEATURES17
|
|
912
|
-
},
|
|
913
|
-
messages: {
|
|
914
|
-
noCommentTextnodes: "Possible misused comment in text node. Comments inside children section of tag should be placed inside braces."
|
|
915
|
-
},
|
|
916
|
-
schema: []
|
|
917
|
-
},
|
|
918
|
-
name: RULE_NAME17,
|
|
919
|
-
create: create17,
|
|
920
|
-
defaultOptions: []
|
|
921
|
-
});
|
|
922
|
-
function create17(context) {
|
|
923
|
-
function hasCommentLike(node) {
|
|
924
|
-
if (AST8.isOneOf([AST_NODE_TYPES.JSXAttribute, AST_NODE_TYPES.JSXExpressionContainer])(node.parent)) {
|
|
925
|
-
return false;
|
|
926
|
-
}
|
|
927
|
-
const rawValue = context.sourceCode.getText(node);
|
|
928
|
-
return /^\s*\/(?:\/|\*)/mu.test(rawValue);
|
|
929
|
-
}
|
|
930
|
-
const visitorFunction = (node) => {
|
|
931
|
-
if (!AST8.isOneOf([AST_NODE_TYPES.JSXElement, AST_NODE_TYPES.JSXFragment])(node.parent)) {
|
|
932
|
-
return;
|
|
933
|
-
}
|
|
934
|
-
if (!hasCommentLike(node)) {
|
|
935
|
-
return;
|
|
936
|
-
}
|
|
937
|
-
if (!node.parent.type.includes("JSX")) {
|
|
938
|
-
return;
|
|
939
|
-
}
|
|
940
|
-
context.report({
|
|
941
|
-
messageId: "noCommentTextnodes",
|
|
942
|
-
node
|
|
943
|
-
});
|
|
944
|
-
};
|
|
945
|
-
return {
|
|
946
|
-
JSXText: visitorFunction,
|
|
947
|
-
Literal: visitorFunction
|
|
948
|
-
};
|
|
949
|
-
}
|
|
950
|
-
var RULE_NAME18 = "no-complex-conditional-rendering";
|
|
951
|
-
var RULE_FEATURES18 = [
|
|
952
|
-
"EXP"
|
|
953
|
-
];
|
|
954
|
-
var no_complex_conditional_rendering_default = createRule({
|
|
955
|
-
meta: {
|
|
956
|
-
type: "problem",
|
|
957
|
-
docs: {
|
|
958
|
-
description: "Disallow complex conditional rendering in JSX expressions.",
|
|
959
|
-
[Symbol.for("rule_features")]: RULE_FEATURES18
|
|
960
|
-
},
|
|
961
|
-
messages: {
|
|
962
|
-
noComplexConditionalRendering: "Avoid complex conditional rendering. Extract the logic into separate elements or components."
|
|
963
|
-
},
|
|
964
|
-
schema: []
|
|
965
|
-
},
|
|
966
|
-
name: RULE_NAME18,
|
|
967
|
-
create: create18,
|
|
968
|
-
defaultOptions: []
|
|
969
|
-
});
|
|
970
|
-
function create18(context) {
|
|
971
|
-
const visitorFunction = (node) => {
|
|
972
|
-
const jsxExpContainer = node.parent?.parent;
|
|
973
|
-
if (!AST8.is(AST_NODE_TYPES.JSXExpressionContainer)(jsxExpContainer)) {
|
|
974
|
-
return;
|
|
975
|
-
}
|
|
976
|
-
if (!AST8.isOneOf([AST_NODE_TYPES.JSXElement, AST_NODE_TYPES.JSXFragment])(jsxExpContainer.parent)) {
|
|
977
|
-
return;
|
|
978
|
-
}
|
|
979
|
-
if (!jsxExpContainer.parent.children.includes(jsxExpContainer)) {
|
|
980
|
-
return;
|
|
981
|
-
}
|
|
982
|
-
context.report({
|
|
983
|
-
messageId: "noComplexConditionalRendering",
|
|
984
|
-
node: jsxExpContainer
|
|
985
|
-
});
|
|
986
|
-
};
|
|
987
|
-
return {
|
|
988
|
-
"JSXExpressionContainer > ConditionalExpression > ConditionalExpression": visitorFunction,
|
|
989
|
-
"JSXExpressionContainer > ConditionalExpression > LogicalExpression": visitorFunction,
|
|
990
|
-
"JSXExpressionContainer > LogicalExpression > ConditionalExpression": visitorFunction,
|
|
991
|
-
"JSXExpressionContainer > LogicalExpression[operator='&&'] > LogicalExpression[operator='||']": visitorFunction,
|
|
992
|
-
"JSXExpressionContainer > LogicalExpression[operator='||'] > LogicalExpression[operator='&&']": visitorFunction
|
|
993
|
-
};
|
|
994
|
-
}
|
|
995
|
-
var RULE_NAME19 = "no-component-will-mount";
|
|
996
|
-
var RULE_FEATURES19 = [
|
|
997
|
-
"MOD"
|
|
998
|
-
];
|
|
999
|
-
var no_component_will_mount_default = createRule({
|
|
1000
|
-
meta: {
|
|
1001
|
-
type: "problem",
|
|
1002
|
-
docs: {
|
|
1003
|
-
description: "Replace usages of `componentWillMount` with `UNSAFE_componentWillMount`.",
|
|
1004
|
-
[Symbol.for("rule_features")]: RULE_FEATURES19
|
|
1005
|
-
},
|
|
1006
|
-
fixable: "code",
|
|
1007
|
-
messages: {
|
|
1008
|
-
noComponentWillMount: "[Deprecated] Use 'UNSAFE_componentWillMount' instead."
|
|
1009
|
-
},
|
|
1010
|
-
schema: []
|
|
1011
|
-
},
|
|
1012
|
-
name: RULE_NAME19,
|
|
1013
|
-
create: create19,
|
|
1014
|
-
defaultOptions: []
|
|
1015
|
-
});
|
|
1016
|
-
function create19(context) {
|
|
1017
|
-
if (!context.sourceCode.text.includes("componentWillMount")) return {};
|
|
1018
|
-
const { ctx, listeners } = ER25.useComponentCollectorLegacy();
|
|
1019
|
-
return {
|
|
1020
|
-
...listeners,
|
|
1021
|
-
"Program:exit"(program) {
|
|
1022
|
-
const components = ctx.getAllComponents(program);
|
|
1023
|
-
for (const { node: component } of components.values()) {
|
|
1024
|
-
const { body } = component.body;
|
|
1025
|
-
for (const member of body) {
|
|
1026
|
-
if (ER25.isComponentWillMount(member)) {
|
|
1027
|
-
context.report({
|
|
1028
|
-
messageId: "noComponentWillMount",
|
|
1029
|
-
node: member,
|
|
1030
|
-
fix(fixer) {
|
|
1031
|
-
if (!("key" in member)) {
|
|
1032
|
-
return null;
|
|
1033
|
-
}
|
|
1034
|
-
return fixer.replaceText(member.key, "UNSAFE_componentWillMount");
|
|
1035
|
-
}
|
|
1036
|
-
});
|
|
1037
|
-
}
|
|
1038
|
-
}
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
};
|
|
1042
|
-
}
|
|
1043
|
-
var RULE_NAME20 = "no-component-will-receive-props";
|
|
1044
|
-
var RULE_FEATURES20 = [
|
|
1045
|
-
"MOD"
|
|
1046
|
-
];
|
|
1047
|
-
var no_component_will_receive_props_default = createRule({
|
|
1048
|
-
meta: {
|
|
1049
|
-
type: "problem",
|
|
1050
|
-
docs: {
|
|
1051
|
-
description: "Replace usages of `componentWillReceiveProps` with `UNSAFE_componentWillReceiveProps`.",
|
|
1052
|
-
[Symbol.for("rule_features")]: RULE_FEATURES20
|
|
1053
|
-
},
|
|
1054
|
-
fixable: "code",
|
|
1055
|
-
messages: {
|
|
1056
|
-
noComponentWillReceiveProps: "[Deprecated] Use 'UNSAFE_componentWillReceiveProps' instead."
|
|
1057
|
-
},
|
|
1058
|
-
schema: []
|
|
1059
|
-
},
|
|
1060
|
-
name: RULE_NAME20,
|
|
1061
|
-
create: create20,
|
|
1062
|
-
defaultOptions: []
|
|
1063
|
-
});
|
|
1064
|
-
function create20(context) {
|
|
1065
|
-
if (!context.sourceCode.text.includes("componentWillReceiveProps")) return {};
|
|
1066
|
-
const { ctx, listeners } = ER25.useComponentCollectorLegacy();
|
|
1067
|
-
return {
|
|
1068
|
-
...listeners,
|
|
1069
|
-
"Program:exit"(program) {
|
|
1070
|
-
const components = ctx.getAllComponents(program);
|
|
1071
|
-
for (const { node: component } of components.values()) {
|
|
1072
|
-
const { body } = component.body;
|
|
1073
|
-
for (const member of body) {
|
|
1074
|
-
if (ER25.isComponentWillReceiveProps(member)) {
|
|
1075
|
-
context.report({
|
|
1076
|
-
messageId: "noComponentWillReceiveProps",
|
|
1077
|
-
node: member,
|
|
1078
|
-
fix(fixer) {
|
|
1079
|
-
if (!("key" in member)) {
|
|
1080
|
-
return null;
|
|
1081
|
-
}
|
|
1082
|
-
return fixer.replaceText(member.key, "UNSAFE_componentWillReceiveProps");
|
|
1083
|
-
}
|
|
1084
|
-
});
|
|
1085
|
-
}
|
|
1086
|
-
}
|
|
1087
|
-
}
|
|
1088
|
-
}
|
|
1089
|
-
};
|
|
1090
|
-
}
|
|
1091
|
-
var RULE_NAME21 = "no-component-will-update";
|
|
1092
|
-
var RULE_FEATURES21 = [
|
|
1093
|
-
"MOD"
|
|
1094
|
-
];
|
|
1095
|
-
var no_component_will_update_default = createRule({
|
|
1096
|
-
meta: {
|
|
1097
|
-
type: "problem",
|
|
1098
|
-
docs: {
|
|
1099
|
-
description: "Replace usages of `componentWillUpdate` with `UNSAFE_componentWillUpdate`.",
|
|
1100
|
-
[Symbol.for("rule_features")]: RULE_FEATURES21
|
|
1101
|
-
},
|
|
1102
|
-
fixable: "code",
|
|
1103
|
-
messages: {
|
|
1104
|
-
noComponentWillUpdate: "[Deprecated] Use 'UNSAFE_componentWillUpdate' instead."
|
|
1105
|
-
},
|
|
1106
|
-
schema: []
|
|
1107
|
-
},
|
|
1108
|
-
name: RULE_NAME21,
|
|
1109
|
-
create: create21,
|
|
1110
|
-
defaultOptions: []
|
|
1111
|
-
});
|
|
1112
|
-
function create21(context) {
|
|
1113
|
-
if (!context.sourceCode.text.includes("componentWillUpdate")) return {};
|
|
1114
|
-
const { ctx, listeners } = ER25.useComponentCollectorLegacy();
|
|
1115
|
-
return {
|
|
1116
|
-
...listeners,
|
|
1117
|
-
"Program:exit"(program) {
|
|
1118
|
-
const components = ctx.getAllComponents(program);
|
|
1119
|
-
for (const { node: component } of components.values()) {
|
|
1120
|
-
const { body } = component.body;
|
|
1121
|
-
for (const member of body) {
|
|
1122
|
-
if (ER25.isComponentWillUpdate(member)) {
|
|
1123
|
-
context.report({
|
|
1124
|
-
messageId: "noComponentWillUpdate",
|
|
1125
|
-
node: member,
|
|
1126
|
-
fix(fixer) {
|
|
1127
|
-
if (!("key" in member)) {
|
|
1128
|
-
return null;
|
|
1129
|
-
}
|
|
1130
|
-
return fixer.replaceText(member.key, "UNSAFE_componentWillUpdate");
|
|
1131
|
-
}
|
|
1132
|
-
});
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
|
-
}
|
|
1136
|
-
}
|
|
1137
|
-
};
|
|
1138
|
-
}
|
|
1139
|
-
var RULE_NAME22 = "no-context-provider";
|
|
1140
|
-
var RULE_FEATURES22 = [
|
|
1141
|
-
"MOD"
|
|
1142
|
-
];
|
|
1143
|
-
var no_context_provider_default = createRule({
|
|
1144
|
-
meta: {
|
|
1145
|
-
type: "problem",
|
|
1146
|
-
docs: {
|
|
1147
|
-
description: "Replace usages of `<Context.Provider>` with `<Context>`.",
|
|
1148
|
-
[Symbol.for("rule_features")]: RULE_FEATURES22
|
|
1149
|
-
},
|
|
1150
|
-
fixable: "code",
|
|
1151
|
-
messages: {
|
|
1152
|
-
noContextProvider: "In React 19, you can render '<Context>' as a provider instead of '<Context.Provider>'."
|
|
1153
|
-
},
|
|
1154
|
-
schema: []
|
|
1155
|
-
},
|
|
1156
|
-
name: RULE_NAME22,
|
|
1157
|
-
create: create22,
|
|
1158
|
-
defaultOptions: []
|
|
1159
|
-
});
|
|
1160
|
-
function create22(context) {
|
|
1161
|
-
if (!context.sourceCode.text.includes("Provider")) return {};
|
|
1162
|
-
const { version: version2 } = getSettingsFromContext(context);
|
|
1163
|
-
if (compare(version2, "19.0.0", "<")) return {};
|
|
1164
|
-
return {
|
|
1165
|
-
JSXElement(node) {
|
|
1166
|
-
const fullName = ER25.getElementType(context, node);
|
|
1167
|
-
const parts = fullName.split(".");
|
|
1168
|
-
const selfName = parts.pop();
|
|
1169
|
-
const contextFullName = parts.join(".");
|
|
1170
|
-
const contextSelfName = parts.pop();
|
|
1171
|
-
if (selfName !== "Provider") return;
|
|
1172
|
-
if (contextSelfName == null) return;
|
|
1173
|
-
context.report({
|
|
1174
|
-
messageId: "noContextProvider",
|
|
1175
|
-
node,
|
|
1176
|
-
fix(fixer) {
|
|
1177
|
-
if (!ER25.isComponentNameLoose(contextSelfName)) return null;
|
|
1178
|
-
const openingElement = node.openingElement;
|
|
1179
|
-
const closingElement = node.closingElement;
|
|
1180
|
-
if (closingElement == null) {
|
|
1181
|
-
return fixer.replaceText(openingElement.name, contextFullName);
|
|
1182
|
-
}
|
|
1183
|
-
return [
|
|
1184
|
-
fixer.replaceText(openingElement.name, contextFullName),
|
|
1185
|
-
fixer.replaceText(closingElement.name, contextFullName)
|
|
1186
|
-
];
|
|
1187
|
-
}
|
|
1188
|
-
});
|
|
1189
|
-
}
|
|
1190
|
-
};
|
|
1191
|
-
}
|
|
1192
|
-
var RULE_NAME23 = "no-create-ref";
|
|
1193
|
-
var RULE_FEATURES23 = [];
|
|
1194
|
-
var no_create_ref_default = createRule({
|
|
1195
|
-
meta: {
|
|
1196
|
-
type: "problem",
|
|
1197
|
-
docs: {
|
|
1198
|
-
description: "Disallow `createRef` in function components.",
|
|
1199
|
-
[Symbol.for("rule_features")]: RULE_FEATURES23
|
|
1200
|
-
},
|
|
1201
|
-
messages: {
|
|
1202
|
-
noCreateRef: "[Deprecated] Use 'useRef' instead."
|
|
1203
|
-
},
|
|
1204
|
-
schema: []
|
|
1205
|
-
},
|
|
1206
|
-
name: RULE_NAME23,
|
|
1207
|
-
create: create23,
|
|
1208
|
-
defaultOptions: []
|
|
1209
|
-
});
|
|
1210
|
-
function create23(context) {
|
|
1211
|
-
return {
|
|
1212
|
-
CallExpression(node) {
|
|
1213
|
-
if (ER25.isCreateRefCall(context, node) && AST8.findParentNode(node, ER25.isClassComponent) == null) {
|
|
1214
|
-
context.report({ messageId: "noCreateRef", node });
|
|
1215
|
-
}
|
|
1216
|
-
}
|
|
1217
|
-
};
|
|
1218
|
-
}
|
|
1219
|
-
var RULE_NAME24 = "no-default-props";
|
|
1220
|
-
var RULE_FEATURES24 = [];
|
|
1221
|
-
var no_default_props_default = createRule({
|
|
1222
|
-
meta: {
|
|
1223
|
-
type: "problem",
|
|
1224
|
-
docs: {
|
|
1225
|
-
description: "Disallow `defaultProps` property in favor of ES6 default parameters.",
|
|
1226
|
-
[Symbol.for("rule_features")]: RULE_FEATURES24
|
|
1227
|
-
},
|
|
1228
|
-
messages: {
|
|
1229
|
-
noDefaultProps: "[Deprecated] Use ES6 default parameters instead."
|
|
1230
|
-
},
|
|
1231
|
-
schema: []
|
|
1232
|
-
},
|
|
1233
|
-
name: RULE_NAME24,
|
|
1234
|
-
create: create24,
|
|
1235
|
-
defaultOptions: []
|
|
1236
|
-
});
|
|
1237
|
-
function create24(context) {
|
|
1238
|
-
if (!context.sourceCode.text.includes("defaultProps")) return {};
|
|
1239
|
-
return {
|
|
1240
|
-
AssignmentExpression(node) {
|
|
1241
|
-
if (node.operator !== "=" || node.left.type !== AST_NODE_TYPES.MemberExpression) {
|
|
1242
|
-
return;
|
|
1243
|
-
}
|
|
1244
|
-
const { object, property } = node.left;
|
|
1245
|
-
if (object.type !== AST_NODE_TYPES.Identifier) {
|
|
1246
|
-
return;
|
|
1247
|
-
}
|
|
1248
|
-
if (property.type !== AST_NODE_TYPES.Identifier || property.name !== "defaultProps") {
|
|
1249
|
-
return;
|
|
1250
|
-
}
|
|
1251
|
-
if (!ER25.isComponentNameLoose(object.name)) {
|
|
1252
|
-
return;
|
|
1253
|
-
}
|
|
1254
|
-
const variable = VAR2.findVariable(object.name, context.sourceCode.getScope(node));
|
|
1255
|
-
const variableNode = VAR2.getVariableInitNode(variable, 0);
|
|
1256
|
-
if (variableNode == null) return;
|
|
1257
|
-
if (!AST8.isFunction(variableNode) && !ER25.isClassComponent(variableNode)) return;
|
|
1258
|
-
context.report({ messageId: "noDefaultProps", node: property });
|
|
1259
|
-
},
|
|
1260
|
-
PropertyDefinition(node) {
|
|
1261
|
-
if (!ER25.isClassComponent(node.parent.parent)) {
|
|
1262
|
-
return;
|
|
1263
|
-
}
|
|
1264
|
-
if (!node.static || node.key.type !== AST_NODE_TYPES.Identifier || node.key.name !== "defaultProps") {
|
|
1265
|
-
return;
|
|
1266
|
-
}
|
|
1267
|
-
context.report({ messageId: "noDefaultProps", node });
|
|
1268
|
-
}
|
|
1269
|
-
};
|
|
1270
|
-
}
|
|
1271
|
-
var RULE_NAME25 = "no-direct-mutation-state";
|
|
1272
|
-
var RULE_FEATURES25 = [];
|
|
1273
|
-
function isConstructorFunction(node) {
|
|
1274
|
-
return AST8.isOneOf([AST_NODE_TYPES.FunctionDeclaration, AST_NODE_TYPES.FunctionExpression])(node) && AST8.isMethodOrProperty(node.parent) && node.parent.key.type === AST_NODE_TYPES.Identifier && node.parent.key.name === "constructor";
|
|
1275
|
-
}
|
|
1276
|
-
var no_direct_mutation_state_default = createRule({
|
|
1277
|
-
meta: {
|
|
1278
|
-
type: "problem",
|
|
1279
|
-
docs: {
|
|
1280
|
-
description: "Disallow direct mutation of `this.state`.",
|
|
1281
|
-
[Symbol.for("rule_features")]: RULE_FEATURES25
|
|
1282
|
-
},
|
|
1283
|
-
messages: {
|
|
1284
|
-
noDirectMutationState: "Do not mutate state directly. Use 'setState()' instead."
|
|
1285
|
-
},
|
|
1286
|
-
schema: []
|
|
1287
|
-
},
|
|
1288
|
-
name: RULE_NAME25,
|
|
1289
|
-
create: create25,
|
|
1290
|
-
defaultOptions: []
|
|
1291
|
-
});
|
|
1292
|
-
function create25(context) {
|
|
1293
|
-
return {
|
|
1294
|
-
AssignmentExpression(node) {
|
|
1295
|
-
if (!ER25.isAssignmentToThisState(node)) return;
|
|
1296
|
-
const parentClass = AST8.findParentNode(
|
|
1297
|
-
node,
|
|
1298
|
-
AST8.isOneOf([
|
|
1299
|
-
AST_NODE_TYPES.ClassDeclaration,
|
|
1300
|
-
AST_NODE_TYPES.ClassExpression
|
|
1301
|
-
])
|
|
1302
|
-
);
|
|
1303
|
-
if (parentClass == null) return;
|
|
1304
|
-
if (ER25.isClassComponent(parentClass) && context.sourceCode.getScope(node).block !== AST8.findParentNode(node, isConstructorFunction)) {
|
|
1305
|
-
context.report({
|
|
1306
|
-
messageId: "noDirectMutationState",
|
|
1307
|
-
node
|
|
1308
|
-
});
|
|
1309
|
-
}
|
|
1310
|
-
}
|
|
1311
|
-
};
|
|
1312
|
-
}
|
|
1313
|
-
var RULE_NAME26 = "no-duplicate-key";
|
|
1314
|
-
var RULE_FEATURES26 = [];
|
|
1315
|
-
var no_duplicate_key_default = createRule({
|
|
1316
|
-
meta: {
|
|
1317
|
-
type: "problem",
|
|
1318
|
-
docs: {
|
|
1319
|
-
description: "Disallow duplicate `key` on elements in the same array or a list of `children`.",
|
|
1320
|
-
[Symbol.for("rule_features")]: RULE_FEATURES26
|
|
1321
|
-
},
|
|
1322
|
-
messages: {
|
|
1323
|
-
noDuplicateKey: "A key must be unique. '{{value}}' is duplicated."
|
|
1324
|
-
},
|
|
1325
|
-
schema: []
|
|
1326
|
-
},
|
|
1327
|
-
name: RULE_NAME26,
|
|
1328
|
-
create: create26,
|
|
1329
|
-
defaultOptions: []
|
|
1330
|
-
});
|
|
1331
|
-
function create26(context) {
|
|
1332
|
-
if (!context.sourceCode.getText().includes("key=")) {
|
|
1333
|
-
return {};
|
|
1334
|
-
}
|
|
1335
|
-
const keyedEntries = /* @__PURE__ */ new Map();
|
|
1336
|
-
function isKeyValueEqual(a, b) {
|
|
1337
|
-
const aValue = a.value;
|
|
1338
|
-
const bValue = b.value;
|
|
1339
|
-
if (aValue == null || bValue == null) {
|
|
1340
|
-
return false;
|
|
1341
|
-
}
|
|
1342
|
-
return AST8.isNodeEqual(aValue, bValue);
|
|
1343
|
-
}
|
|
1344
|
-
return {
|
|
1345
|
-
"JSXAttribute[name.name='key']"(node) {
|
|
1346
|
-
const jsxElement = node.parent.parent;
|
|
1347
|
-
switch (jsxElement.parent.type) {
|
|
1348
|
-
case AST_NODE_TYPES.ArrayExpression:
|
|
1349
|
-
case AST_NODE_TYPES.JSXElement:
|
|
1350
|
-
case AST_NODE_TYPES.JSXFragment: {
|
|
1351
|
-
const root = jsxElement.parent;
|
|
1352
|
-
const prevKeys = keyedEntries.get(root)?.keys ?? [];
|
|
1353
|
-
keyedEntries.set(root, {
|
|
1354
|
-
hasDuplicate: prevKeys.some((prevKey) => isKeyValueEqual(prevKey, node)),
|
|
1355
|
-
keys: [...prevKeys, node],
|
|
1356
|
-
root: jsxElement.parent
|
|
1357
|
-
});
|
|
1358
|
-
break;
|
|
1359
|
-
}
|
|
1360
|
-
default: {
|
|
1361
|
-
const call = AST8.findParentNode(jsxElement, AST8.isArrayMapCall);
|
|
1362
|
-
const iter = AST8.findParentNode(jsxElement, (n) => n === call || AST8.isFunction(n));
|
|
1363
|
-
if (!AST8.isFunction(iter)) return;
|
|
1364
|
-
const arg0 = call?.arguments[0];
|
|
1365
|
-
if (call == null || arg0 == null) return;
|
|
1366
|
-
if (AST8.getJSExpression(arg0) !== iter) {
|
|
1367
|
-
return;
|
|
1368
|
-
}
|
|
1369
|
-
keyedEntries.set(call, {
|
|
1370
|
-
hasDuplicate: node.value?.type === AST_NODE_TYPES.Literal,
|
|
1371
|
-
keys: [node],
|
|
1372
|
-
root: call
|
|
1373
|
-
});
|
|
1374
|
-
}
|
|
1375
|
-
}
|
|
1376
|
-
},
|
|
1377
|
-
"Program:exit"() {
|
|
1378
|
-
for (const { hasDuplicate, keys } of keyedEntries.values()) {
|
|
1379
|
-
if (!hasDuplicate) {
|
|
1380
|
-
continue;
|
|
1381
|
-
}
|
|
1382
|
-
for (const key of keys) {
|
|
1383
|
-
context.report({
|
|
1384
|
-
messageId: "noDuplicateKey",
|
|
1385
|
-
node: key,
|
|
1386
|
-
data: {
|
|
1387
|
-
value: context.sourceCode.getText(key)
|
|
1388
|
-
}
|
|
1389
|
-
});
|
|
1390
|
-
}
|
|
1391
|
-
}
|
|
1392
|
-
}
|
|
1393
|
-
};
|
|
1394
|
-
}
|
|
1395
|
-
var RULE_NAME27 = "no-forward-ref";
|
|
1396
|
-
var RULE_FEATURES27 = [
|
|
1397
|
-
"MOD"
|
|
1398
|
-
];
|
|
1399
|
-
var no_forward_ref_default = createRule({
|
|
1400
|
-
meta: {
|
|
1401
|
-
type: "problem",
|
|
1402
|
-
docs: {
|
|
1403
|
-
description: "Replaces usages of `forwardRef` with passing `ref` as a prop.",
|
|
1404
|
-
[Symbol.for("rule_features")]: RULE_FEATURES27
|
|
1405
|
-
},
|
|
1406
|
-
fixable: "code",
|
|
1407
|
-
messages: {
|
|
1408
|
-
noForwardRef: "In React 19, 'forwardRef' is no longer necessary. Pass 'ref' as a prop instead."
|
|
1409
|
-
},
|
|
1410
|
-
schema: []
|
|
1411
|
-
},
|
|
1412
|
-
name: RULE_NAME27,
|
|
1413
|
-
create: create27,
|
|
1414
|
-
defaultOptions: []
|
|
1415
|
-
});
|
|
1416
|
-
function create27(context) {
|
|
1417
|
-
if (!context.sourceCode.text.includes("forwardRef")) {
|
|
1418
|
-
return {};
|
|
1419
|
-
}
|
|
1420
|
-
const { version: version2 } = getSettingsFromContext(context);
|
|
1421
|
-
if (compare(version2, "19.0.0", "<")) {
|
|
1422
|
-
return {};
|
|
1423
|
-
}
|
|
1424
|
-
return {
|
|
1425
|
-
CallExpression(node) {
|
|
1426
|
-
if (!ER25.isForwardRefCall(context, node)) {
|
|
1427
|
-
return;
|
|
1428
|
-
}
|
|
1429
|
-
const id = AST8.getFunctionId(node);
|
|
1430
|
-
context.report({
|
|
1431
|
-
messageId: "noForwardRef",
|
|
1432
|
-
node: id ?? node,
|
|
1433
|
-
fix: getFix(context, node)
|
|
1434
|
-
});
|
|
1435
|
-
}
|
|
1436
|
-
};
|
|
1437
|
-
}
|
|
1438
|
-
function getFix(context, node) {
|
|
1439
|
-
return (fixer) => {
|
|
1440
|
-
const [componentNode] = node.arguments;
|
|
1441
|
-
if (componentNode == null || !AST8.isFunction(componentNode)) {
|
|
1442
|
-
return [];
|
|
1443
|
-
}
|
|
1444
|
-
return [
|
|
1445
|
-
// unwrap component from forwardRef call
|
|
1446
|
-
fixer.removeRange([node.range[0], componentNode.range[0]]),
|
|
1447
|
-
fixer.removeRange([componentNode.range[1], node.range[1]]),
|
|
1448
|
-
// update component props and ref arguments to match the new signature
|
|
1449
|
-
...getComponentPropsFixes(
|
|
1450
|
-
context,
|
|
1451
|
-
fixer,
|
|
1452
|
-
componentNode,
|
|
1453
|
-
node.typeArguments?.params ?? []
|
|
1454
|
-
)
|
|
1455
|
-
];
|
|
1456
|
-
};
|
|
1457
|
-
}
|
|
1458
|
-
function getComponentPropsFixes(context, fixer, node, typeArguments) {
|
|
1459
|
-
const getText = (node2) => context.sourceCode.getText(node2);
|
|
1460
|
-
const [arg0, arg1] = node.params;
|
|
1461
|
-
const [typeArg0, typeArg1] = typeArguments;
|
|
1462
|
-
if (arg0 == null) {
|
|
1463
|
-
return [];
|
|
1464
|
-
}
|
|
1465
|
-
const fixedArg0Text = match(arg0).with({ type: AST_NODE_TYPES.Identifier }, (n) => `...${n.name}`).with({ type: AST_NODE_TYPES.ObjectPattern }, (n) => n.properties.map(getText).join(", ")).otherwise(() => null);
|
|
1466
|
-
const fixedArg1Text = match(arg1).with(P.nullish, () => "ref").with({ type: AST_NODE_TYPES.Identifier, name: "ref" }, () => "ref").with({ type: AST_NODE_TYPES.Identifier, name: P.string }, (n) => `ref: ${n.name}`).otherwise(() => null);
|
|
1467
|
-
if (fixedArg0Text == null || fixedArg1Text == null) {
|
|
1468
|
-
return [];
|
|
1469
|
-
}
|
|
1470
|
-
if (typeArg0 == null || typeArg1 == null) {
|
|
1471
|
-
return [
|
|
1472
|
-
fixer.replaceText(
|
|
1473
|
-
arg0,
|
|
1474
|
-
[
|
|
1475
|
-
"{",
|
|
1476
|
-
fixedArg1Text + ",",
|
|
1477
|
-
fixedArg0Text,
|
|
1478
|
-
"}"
|
|
1479
|
-
].join(" ")
|
|
1480
|
-
),
|
|
1481
|
-
...arg1 == null ? [] : [fixer.remove(arg1), fixer.removeRange([arg0.range[1], arg1.range[0]])]
|
|
1482
|
-
];
|
|
1483
|
-
}
|
|
1484
|
-
const typeArg0Text = getText(typeArg0);
|
|
1485
|
-
const typeArg1Text = getText(typeArg1);
|
|
1486
|
-
return [
|
|
1487
|
-
fixer.replaceText(
|
|
1488
|
-
arg0,
|
|
1489
|
-
[
|
|
1490
|
-
"{",
|
|
1491
|
-
fixedArg1Text + ",",
|
|
1492
|
-
fixedArg0Text,
|
|
1493
|
-
"}:",
|
|
1494
|
-
typeArg1Text,
|
|
1495
|
-
"&",
|
|
1496
|
-
"{",
|
|
1497
|
-
`ref?:`,
|
|
1498
|
-
`React.RefObject<${typeArg0Text} | null>`,
|
|
1499
|
-
"}"
|
|
1500
|
-
].join(" ")
|
|
1501
|
-
),
|
|
1502
|
-
...arg1 == null ? [] : [fixer.remove(arg1), fixer.removeRange([arg0.range[1], arg1.range[0]])]
|
|
1503
|
-
];
|
|
1504
|
-
}
|
|
1505
|
-
var RULE_NAME28 = "no-implicit-key";
|
|
1506
|
-
var RULE_FEATURES28 = [
|
|
1507
|
-
"EXP"
|
|
1508
|
-
];
|
|
1509
|
-
var no_implicit_key_default = createRule({
|
|
1510
|
-
meta: {
|
|
1511
|
-
type: "problem",
|
|
1512
|
-
docs: {
|
|
1513
|
-
description: "Prevents `key` from not being explicitly specified (e.g. spreading `key` from objects).",
|
|
1514
|
-
[Symbol.for("rule_features")]: RULE_FEATURES28
|
|
1515
|
-
},
|
|
1516
|
-
messages: {
|
|
1517
|
-
noImplicitKey: "Do not use implicit 'key' props."
|
|
1518
|
-
},
|
|
1519
|
-
schema: []
|
|
1520
|
-
},
|
|
1521
|
-
name: RULE_NAME28,
|
|
1522
|
-
create: create28,
|
|
1523
|
-
defaultOptions: []
|
|
1524
|
-
});
|
|
1525
|
-
function create28(context) {
|
|
1526
|
-
return {
|
|
1527
|
-
JSXOpeningElement(node) {
|
|
1528
|
-
const initialScope = context.sourceCode.getScope(node);
|
|
1529
|
-
const keyProp = ER25.getAttribute(context, "key", node.attributes, initialScope);
|
|
1530
|
-
const isKeyPropOnElement = node.attributes.some(
|
|
1531
|
-
(n) => n.type === AST_NODE_TYPES.JSXAttribute && n.name.type === AST_NODE_TYPES.JSXIdentifier && n.name.name === "key"
|
|
1532
|
-
);
|
|
1533
|
-
if (keyProp != null && !isKeyPropOnElement) {
|
|
1534
|
-
context.report({ messageId: "noImplicitKey", node: keyProp });
|
|
1535
|
-
}
|
|
1536
|
-
}
|
|
1537
|
-
};
|
|
1538
|
-
}
|
|
1539
|
-
var RULE_NAME29 = "no-leaked-conditional-rendering";
|
|
1540
|
-
var RULE_FEATURES29 = [
|
|
1541
|
-
"TSC"
|
|
1542
|
-
];
|
|
1543
|
-
var tsHelpers = {
|
|
1544
|
-
isAnyType: (type) => isTypeFlagSet(type, ts.TypeFlags.TypeParameter | ts.TypeFlags.Any),
|
|
1545
|
-
isBigIntType: (type) => isTypeFlagSet(type, ts.TypeFlags.BigIntLike),
|
|
1546
|
-
isBooleanType: (type) => isTypeFlagSet(type, ts.TypeFlags.BooleanLike),
|
|
1547
|
-
isEnumType: (type) => isTypeFlagSet(type, ts.TypeFlags.EnumLike),
|
|
1548
|
-
isFalsyBigIntType: (type) => type.isLiteral() && isMatching({ value: { base10Value: "0" } }, type),
|
|
1549
|
-
isFalsyNumberType: (type) => type.isNumberLiteral() && type.value === 0,
|
|
1550
|
-
isFalsyStringType: (type) => type.isStringLiteral() && type.value === "",
|
|
1551
|
-
isNeverType: (type) => isTypeFlagSet(type, ts.TypeFlags.Never),
|
|
1552
|
-
isNullishType: (type) => isTypeFlagSet(
|
|
1553
|
-
type,
|
|
1554
|
-
ts.TypeFlags.Null | ts.TypeFlags.Undefined | ts.TypeFlags.VoidLike
|
|
1555
|
-
),
|
|
1556
|
-
isNumberType: (type) => isTypeFlagSet(type, ts.TypeFlags.NumberLike),
|
|
1557
|
-
isObjectType: (type) => !isTypeFlagSet(
|
|
1558
|
-
type,
|
|
1559
|
-
ts.TypeFlags.Null | ts.TypeFlags.Undefined | ts.TypeFlags.VoidLike | ts.TypeFlags.BooleanLike | ts.TypeFlags.StringLike | ts.TypeFlags.NumberLike | ts.TypeFlags.BigIntLike | ts.TypeFlags.TypeParameter | ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Never
|
|
1560
|
-
),
|
|
1561
|
-
isStringType: (type) => isTypeFlagSet(type, ts.TypeFlags.StringLike),
|
|
1562
|
-
isTruthyBigIntType: (type) => type.isLiteral() && isMatching({ value: { base10Value: P.not("0") } }, type),
|
|
1563
|
-
isTruthyNumberType: (type) => type.isNumberLiteral() && type.value !== 0,
|
|
1564
|
-
isTruthyStringType: (type) => type.isStringLiteral() && type.value !== "",
|
|
1565
|
-
isUnknownType: (type) => isTypeFlagSet(type, ts.TypeFlags.Unknown)
|
|
1566
|
-
};
|
|
1567
|
-
function inspectVariantTypes(types) {
|
|
1568
|
-
const variantTypes = /* @__PURE__ */ new Set();
|
|
1569
|
-
if (types.some(tsHelpers.isUnknownType)) {
|
|
1570
|
-
variantTypes.add("unknown");
|
|
1571
|
-
return variantTypes;
|
|
1572
|
-
}
|
|
1573
|
-
if (types.some(tsHelpers.isNullishType)) {
|
|
1574
|
-
variantTypes.add("nullish");
|
|
1575
|
-
}
|
|
1576
|
-
const booleans = types.filter(tsHelpers.isBooleanType);
|
|
1577
|
-
switch (true) {
|
|
1578
|
-
case (booleans.length === 1 && booleans[0] != null): {
|
|
1579
|
-
const first = booleans[0];
|
|
1580
|
-
if (isTrueLiteralType(first)) {
|
|
1581
|
-
variantTypes.add("truthy boolean");
|
|
1582
|
-
} else if (isFalseLiteralType(first)) {
|
|
1583
|
-
variantTypes.add("falsy boolean");
|
|
1584
|
-
}
|
|
1585
|
-
break;
|
|
1586
|
-
}
|
|
1587
|
-
case booleans.length === 2: {
|
|
1588
|
-
variantTypes.add("boolean");
|
|
1589
|
-
break;
|
|
1590
|
-
}
|
|
1591
|
-
}
|
|
1592
|
-
const strings = types.filter(tsHelpers.isStringType);
|
|
1593
|
-
if (strings.length > 0) {
|
|
1594
|
-
const evaluated = match(strings).when((types2) => types2.every(tsHelpers.isTruthyStringType), () => "truthy string").when((types2) => types2.every(tsHelpers.isFalsyStringType), () => "falsy string").otherwise(() => "string");
|
|
1595
|
-
variantTypes.add(evaluated);
|
|
1596
|
-
}
|
|
1597
|
-
const bigints = types.filter(tsHelpers.isBigIntType);
|
|
1598
|
-
if (bigints.length > 0) {
|
|
1599
|
-
const evaluated = match(bigints).when((types2) => types2.every(tsHelpers.isTruthyBigIntType), () => "truthy bigint").when((types2) => types2.every(tsHelpers.isFalsyBigIntType), () => "falsy bigint").otherwise(() => "bigint");
|
|
1600
|
-
variantTypes.add(evaluated);
|
|
1601
|
-
}
|
|
1602
|
-
const numbers = types.filter(tsHelpers.isNumberType);
|
|
1603
|
-
if (numbers.length > 0) {
|
|
1604
|
-
const evaluated = match(numbers).when((types2) => types2.every(tsHelpers.isTruthyNumberType), () => "truthy number").when((types2) => types2.every(tsHelpers.isFalsyNumberType), () => "falsy number").otherwise(() => "number");
|
|
1605
|
-
variantTypes.add(evaluated);
|
|
1606
|
-
}
|
|
1607
|
-
if (types.some(tsHelpers.isEnumType)) {
|
|
1608
|
-
variantTypes.add("enum");
|
|
1609
|
-
}
|
|
1610
|
-
if (types.some(tsHelpers.isObjectType)) {
|
|
1611
|
-
variantTypes.add("object");
|
|
1612
|
-
}
|
|
1613
|
-
if (types.some(tsHelpers.isAnyType)) {
|
|
1614
|
-
variantTypes.add("any");
|
|
1615
|
-
}
|
|
1616
|
-
if (types.some(tsHelpers.isNeverType)) {
|
|
1617
|
-
variantTypes.add("never");
|
|
1618
|
-
}
|
|
1619
|
-
return variantTypes;
|
|
1620
|
-
}
|
|
1621
|
-
var no_leaked_conditional_rendering_default = createRule({
|
|
1622
|
-
meta: {
|
|
1623
|
-
type: "problem",
|
|
1624
|
-
docs: {
|
|
1625
|
-
description: "Prevents problematic leaked values from being rendered.",
|
|
1626
|
-
[Symbol.for("rule_features")]: RULE_FEATURES29
|
|
1627
|
-
},
|
|
1628
|
-
messages: {
|
|
1629
|
-
noLeakedConditionalRendering: "Potential leaked value {{value}} that might cause unintentionally rendered values or rendering crashes."
|
|
1630
|
-
},
|
|
1631
|
-
schema: []
|
|
1632
|
-
},
|
|
1633
|
-
name: RULE_NAME29,
|
|
1634
|
-
create: create29,
|
|
1635
|
-
defaultOptions: []
|
|
1636
|
-
});
|
|
1637
|
-
function create29(context) {
|
|
1638
|
-
if (!context.sourceCode.text.includes("&&")) return {};
|
|
1639
|
-
const { version: version2 } = getSettingsFromContext(context);
|
|
1640
|
-
const allowedVariants = [
|
|
1641
|
-
"any",
|
|
1642
|
-
"boolean",
|
|
1643
|
-
"nullish",
|
|
1644
|
-
"object",
|
|
1645
|
-
"falsy boolean",
|
|
1646
|
-
"truthy bigint",
|
|
1647
|
-
"truthy boolean",
|
|
1648
|
-
"truthy number",
|
|
1649
|
-
"truthy string",
|
|
1650
|
-
...compare(version2, "18.0.0", "<") ? [] : ["string", "falsy string"]
|
|
1651
|
-
];
|
|
1652
|
-
const services = ESLintUtils.getParserServices(context, false);
|
|
1653
|
-
function getReportDescriptor(node) {
|
|
1654
|
-
if (node == null) return _;
|
|
1655
|
-
if (AST8.is(AST_NODE_TYPES.JSXExpressionContainer)(node)) return getReportDescriptor(node.expression);
|
|
1656
|
-
if (AST8.isJSX(node)) return _;
|
|
1657
|
-
if (AST8.isTypeExpression(node)) return getReportDescriptor(node.expression);
|
|
1658
|
-
return match(node).with({ type: AST_NODE_TYPES.LogicalExpression, operator: "&&" }, ({ left, right }) => {
|
|
1659
|
-
const isLeftUnaryNot = left.type === AST_NODE_TYPES.UnaryExpression && left.operator === "!";
|
|
1660
|
-
if (isLeftUnaryNot) {
|
|
1661
|
-
return getReportDescriptor(right);
|
|
1662
|
-
}
|
|
1663
|
-
const initialScope = context.sourceCode.getScope(left);
|
|
1664
|
-
const isLeftNan = left.type === AST_NODE_TYPES.Identifier && left.name === "NaN" || VAR2.toStaticValue({ kind: "lazy", node: left, initialScope }).value === "NaN";
|
|
1665
|
-
if (isLeftNan) {
|
|
1666
|
-
return {
|
|
1667
|
-
messageId: "noLeakedConditionalRendering",
|
|
1668
|
-
node: left,
|
|
1669
|
-
data: { value: context.sourceCode.getText(left) }
|
|
1670
|
-
};
|
|
1671
|
-
}
|
|
1672
|
-
const leftType = getConstrainedTypeAtLocation(services, left);
|
|
1673
|
-
const leftTypeVariants = inspectVariantTypes(unionTypeParts(leftType));
|
|
1674
|
-
const isLeftValid = Array.from(leftTypeVariants.values()).every((type) => allowedVariants.some((allowed) => allowed === type));
|
|
1675
|
-
if (isLeftValid) {
|
|
1676
|
-
return getReportDescriptor(right);
|
|
1677
|
-
}
|
|
1678
|
-
return {
|
|
1679
|
-
messageId: "noLeakedConditionalRendering",
|
|
1680
|
-
node: left,
|
|
1681
|
-
data: { value: context.sourceCode.getText(left) }
|
|
1682
|
-
};
|
|
1683
|
-
}).with({ type: AST_NODE_TYPES.ConditionalExpression }, ({ alternate, consequent }) => {
|
|
1684
|
-
return getReportDescriptor(consequent) ?? getReportDescriptor(alternate);
|
|
1685
|
-
}).with({ type: AST_NODE_TYPES.Identifier }, (n) => {
|
|
1686
|
-
const variable = VAR2.findVariable(n.name, context.sourceCode.getScope(n));
|
|
1687
|
-
const variableDefNode = variable?.defs.at(0)?.node;
|
|
1688
|
-
return match(variableDefNode).with({ init: P.select({ type: P.not(AST_NODE_TYPES.VariableDeclaration) }) }, getReportDescriptor).otherwise(() => _);
|
|
1689
|
-
}).otherwise(() => _);
|
|
1690
|
-
}
|
|
1691
|
-
return {
|
|
1692
|
-
JSXExpressionContainer: flow(getReportDescriptor, Reporter.make(context).send)
|
|
1693
|
-
};
|
|
1694
|
-
}
|
|
1695
|
-
var RULE_NAME30 = "no-missing-component-display-name";
|
|
1696
|
-
var RULE_FEATURES30 = [];
|
|
1697
|
-
var no_missing_component_display_name_default = createRule({
|
|
1698
|
-
meta: {
|
|
1699
|
-
type: "problem",
|
|
1700
|
-
docs: {
|
|
1701
|
-
description: "Enforces that all components have a `displayName` which can be used in devtools.",
|
|
1702
|
-
[Symbol.for("rule_features")]: RULE_FEATURES30
|
|
1703
|
-
},
|
|
1704
|
-
messages: {
|
|
1705
|
-
noMissingComponentDisplayName: "Add missing 'displayName' for component."
|
|
1706
|
-
},
|
|
1707
|
-
schema: []
|
|
1708
|
-
},
|
|
1709
|
-
name: RULE_NAME30,
|
|
1710
|
-
create: create30,
|
|
1711
|
-
defaultOptions: []
|
|
1712
|
-
});
|
|
1713
|
-
function create30(context) {
|
|
1714
|
-
if (!context.sourceCode.text.includes("memo") && !context.sourceCode.text.includes("forwardRef")) return {};
|
|
1715
|
-
const {
|
|
1716
|
-
ctx,
|
|
1717
|
-
listeners
|
|
1718
|
-
} = ER25.useComponentCollector(
|
|
1719
|
-
context,
|
|
1720
|
-
{
|
|
1721
|
-
collectDisplayName: true,
|
|
1722
|
-
collectHookCalls: false,
|
|
1723
|
-
hint: ER25.DEFAULT_COMPONENT_DETECTION_HINT
|
|
1724
|
-
}
|
|
1725
|
-
);
|
|
1726
|
-
return {
|
|
1727
|
-
...listeners,
|
|
1728
|
-
"Program:exit"(program) {
|
|
1729
|
-
const components = ctx.getAllComponents(program);
|
|
1730
|
-
for (const { node, displayName, flag } of components.values()) {
|
|
1731
|
-
const isMemoOrForwardRef = (flag & (ER25.ComponentFlag.ForwardRef | ER25.ComponentFlag.Memo)) > 0n;
|
|
1732
|
-
if (AST8.getFunctionId(node) != null) {
|
|
1733
|
-
continue;
|
|
1734
|
-
}
|
|
1735
|
-
if (!isMemoOrForwardRef) {
|
|
1736
|
-
continue;
|
|
1737
|
-
}
|
|
1738
|
-
if (displayName == null) {
|
|
1739
|
-
const id = AST8.getFunctionId(node);
|
|
1740
|
-
context.report({
|
|
1741
|
-
messageId: "noMissingComponentDisplayName",
|
|
1742
|
-
node: id ?? node
|
|
1743
|
-
});
|
|
1744
|
-
}
|
|
1745
|
-
}
|
|
1746
|
-
}
|
|
1747
|
-
};
|
|
1748
|
-
}
|
|
1749
|
-
var RULE_NAME31 = "no-missing-context-display-name";
|
|
1750
|
-
var RULE_FEATURES31 = [];
|
|
1751
|
-
var no_missing_context_display_name_default = createRule({
|
|
1752
|
-
meta: {
|
|
1753
|
-
type: "problem",
|
|
1754
|
-
docs: {
|
|
1755
|
-
description: "Enforces that all contexts have a `displayName` which can be used in devtools.",
|
|
1756
|
-
[Symbol.for("rule_features")]: RULE_FEATURES31
|
|
1757
|
-
},
|
|
1758
|
-
messages: {
|
|
1759
|
-
noMissingContextDisplayName: "Add missing 'displayName' for context."
|
|
1760
|
-
},
|
|
1761
|
-
schema: []
|
|
1762
|
-
},
|
|
1763
|
-
name: RULE_NAME31,
|
|
1764
|
-
create: create31,
|
|
1765
|
-
defaultOptions: []
|
|
1766
|
-
});
|
|
1767
|
-
function create31(context) {
|
|
1768
|
-
if (!context.sourceCode.text.includes("createContext")) return {};
|
|
1769
|
-
const createCalls = [];
|
|
1770
|
-
const displayNameAssignments = [];
|
|
1771
|
-
return {
|
|
1772
|
-
CallExpression(node) {
|
|
1773
|
-
if (!ER25.isCreateContextCall(context, node)) return;
|
|
1774
|
-
createCalls.push(node);
|
|
1775
|
-
},
|
|
1776
|
-
"Program:exit"() {
|
|
1777
|
-
for (const call of createCalls) {
|
|
1778
|
-
const id = ER25.getInstanceId(call);
|
|
1779
|
-
if (id == null) {
|
|
1780
|
-
context.report({
|
|
1781
|
-
messageId: "noMissingContextDisplayName",
|
|
1782
|
-
node: call
|
|
1783
|
-
});
|
|
1784
|
-
continue;
|
|
1785
|
-
}
|
|
1786
|
-
const hasDisplayNameAssignment = displayNameAssignments.some((node) => {
|
|
1787
|
-
const left = node.left;
|
|
1788
|
-
if (left.type !== AST_NODE_TYPES.MemberExpression) return false;
|
|
1789
|
-
const object = left.object;
|
|
1790
|
-
return ER25.isInstanceIdEqual(context, id, object);
|
|
1791
|
-
});
|
|
1792
|
-
if (!hasDisplayNameAssignment) {
|
|
1793
|
-
context.report({
|
|
1794
|
-
messageId: "noMissingContextDisplayName",
|
|
1795
|
-
node: id
|
|
1796
|
-
});
|
|
1797
|
-
}
|
|
1798
|
-
}
|
|
1799
|
-
},
|
|
1800
|
-
[Selector.DISPLAY_NAME_ASSIGNMENT_EXPRESSION](node) {
|
|
1801
|
-
displayNameAssignments.push(node);
|
|
1802
|
-
}
|
|
1803
|
-
};
|
|
1804
|
-
}
|
|
1805
|
-
var RULE_NAME32 = "no-missing-key";
|
|
1806
|
-
var RULE_FEATURES32 = [];
|
|
1807
|
-
var no_missing_key_default = createRule({
|
|
1808
|
-
meta: {
|
|
1809
|
-
type: "problem",
|
|
1810
|
-
docs: {
|
|
1811
|
-
description: "Disallow missing `key` on items in list rendering.",
|
|
1812
|
-
[Symbol.for("rule_features")]: RULE_FEATURES32
|
|
1813
|
-
},
|
|
1814
|
-
messages: {
|
|
1815
|
-
missingKey: "Missing 'key' for element when rendering list.",
|
|
1816
|
-
unexpectedFragmentSyntax: "Use fragment component instead of '<>' because it does not support `key`."
|
|
1817
|
-
},
|
|
1818
|
-
schema: []
|
|
1819
|
-
},
|
|
1820
|
-
name: RULE_NAME32,
|
|
1821
|
-
create: create32,
|
|
1822
|
-
defaultOptions: []
|
|
1823
|
-
});
|
|
1824
|
-
function create32(context) {
|
|
1825
|
-
const report = Reporter.make(context);
|
|
1826
|
-
const state = { isWithinChildrenToArray: false };
|
|
1827
|
-
function checkIteratorElement(node) {
|
|
1828
|
-
switch (node.type) {
|
|
1829
|
-
case AST_NODE_TYPES.JSXElement: {
|
|
1830
|
-
const initialScope = context.sourceCode.getScope(node);
|
|
1831
|
-
if (!ER25.hasAttribute(context, "key", node.openingElement.attributes, initialScope)) {
|
|
1832
|
-
return {
|
|
1833
|
-
messageId: "missingKey",
|
|
1834
|
-
node
|
|
1835
|
-
};
|
|
1836
|
-
}
|
|
1837
|
-
return null;
|
|
1838
|
-
}
|
|
1839
|
-
case AST_NODE_TYPES.JSXFragment: {
|
|
1840
|
-
return {
|
|
1841
|
-
messageId: "unexpectedFragmentSyntax",
|
|
1842
|
-
node
|
|
1843
|
-
};
|
|
1844
|
-
}
|
|
1845
|
-
default:
|
|
1846
|
-
return null;
|
|
1847
|
-
}
|
|
1848
|
-
}
|
|
1849
|
-
function checkExpression(node) {
|
|
1850
|
-
switch (node.type) {
|
|
1851
|
-
case AST_NODE_TYPES.ConditionalExpression:
|
|
1852
|
-
if ("consequent" in node) {
|
|
1853
|
-
return checkIteratorElement(node.consequent) ?? checkIteratorElement(node.alternate);
|
|
1854
|
-
}
|
|
1855
|
-
return null;
|
|
1856
|
-
case AST_NODE_TYPES.JSXElement:
|
|
1857
|
-
case AST_NODE_TYPES.JSXFragment:
|
|
1858
|
-
return checkIteratorElement(node);
|
|
1859
|
-
case AST_NODE_TYPES.LogicalExpression:
|
|
1860
|
-
if ("left" in node) {
|
|
1861
|
-
return checkIteratorElement(node.left) ?? checkIteratorElement(node.right);
|
|
1862
|
-
}
|
|
1863
|
-
return null;
|
|
1864
|
-
default:
|
|
1865
|
-
return null;
|
|
1866
|
-
}
|
|
1867
|
-
}
|
|
1868
|
-
function checkBlockStatement(node) {
|
|
1869
|
-
const descriptors = [];
|
|
1870
|
-
for (const statement of AST8.getNestedReturnStatements(node)) {
|
|
1871
|
-
if (statement.argument == null) continue;
|
|
1872
|
-
const descriptor = checkIteratorElement(statement.argument);
|
|
1873
|
-
if (descriptor != null) descriptors.push(descriptor);
|
|
1874
|
-
}
|
|
1875
|
-
return descriptors;
|
|
1876
|
-
}
|
|
1877
|
-
return {
|
|
1878
|
-
ArrayExpression(node) {
|
|
1879
|
-
if (state.isWithinChildrenToArray) {
|
|
1880
|
-
return;
|
|
1881
|
-
}
|
|
1882
|
-
const elements = node.elements.filter(AST8.is(AST_NODE_TYPES.JSXElement));
|
|
1883
|
-
if (elements.length === 0) {
|
|
1884
|
-
return;
|
|
1885
|
-
}
|
|
1886
|
-
const initialScope = context.sourceCode.getScope(node);
|
|
1887
|
-
for (const element of elements) {
|
|
1888
|
-
if (!ER25.hasAttribute(context, "key", element.openingElement.attributes, initialScope)) {
|
|
1889
|
-
report.send({
|
|
1890
|
-
messageId: "missingKey",
|
|
1891
|
-
node: element
|
|
1892
|
-
});
|
|
1893
|
-
}
|
|
1894
|
-
}
|
|
1895
|
-
},
|
|
1896
|
-
CallExpression(node) {
|
|
1897
|
-
state.isWithinChildrenToArray ||= ER25.isChildrenToArrayCall(context, node);
|
|
1898
|
-
if (state.isWithinChildrenToArray) return;
|
|
1899
|
-
const callback = match(node).when(AST8.isArrayMapCall, (n) => n.arguments[0]).when(AST8.isArrayFromCall, (n) => n.arguments[1]).otherwise(() => null);
|
|
1900
|
-
if (!AST8.isFunction(callback)) return;
|
|
1901
|
-
const body = callback.body;
|
|
1902
|
-
if (body.type === AST_NODE_TYPES.BlockStatement) {
|
|
1903
|
-
checkBlockStatement(body).forEach(report.send);
|
|
1904
|
-
return;
|
|
1905
|
-
}
|
|
1906
|
-
report.send(checkExpression(body));
|
|
1907
|
-
},
|
|
1908
|
-
"CallExpression:exit"(node) {
|
|
1909
|
-
if (!ER25.isChildrenToArrayCall(context, node)) {
|
|
1910
|
-
return;
|
|
1911
|
-
}
|
|
1912
|
-
state.isWithinChildrenToArray = false;
|
|
1913
|
-
},
|
|
1914
|
-
JSXFragment(node) {
|
|
1915
|
-
if (state.isWithinChildrenToArray) {
|
|
1916
|
-
return;
|
|
1917
|
-
}
|
|
1918
|
-
if (node.parent.type === AST_NODE_TYPES.ArrayExpression) {
|
|
1919
|
-
report.send({
|
|
1920
|
-
messageId: "unexpectedFragmentSyntax",
|
|
1921
|
-
node
|
|
1922
|
-
});
|
|
1923
|
-
}
|
|
1924
|
-
}
|
|
1925
|
-
};
|
|
1926
|
-
}
|
|
1927
|
-
var RULE_NAME33 = "no-misused-capture-owner-stack";
|
|
1928
|
-
var RULE_FEATURES33 = [
|
|
1929
|
-
"EXP"
|
|
1930
|
-
];
|
|
1931
|
-
var no_misused_capture_owner_stack_default = createRule({
|
|
1932
|
-
meta: {
|
|
1933
|
-
type: "problem",
|
|
1934
|
-
docs: {
|
|
1935
|
-
description: "Prevents incorrect usage of `captureOwnerStack`.",
|
|
1936
|
-
[Symbol.for("rule_features")]: RULE_FEATURES33
|
|
1937
|
-
},
|
|
1938
|
-
fixable: "code",
|
|
1939
|
-
messages: {
|
|
1940
|
-
useNamespaceImport: "Don't use named imports of 'captureOwnerStack' in files that are bundled for development and production. Use a namespace import instead.",
|
|
1941
|
-
// eslint-disable-next-line perfectionist/sort-objects
|
|
1942
|
-
missingDevelopmentOnlyCheck: `Don't call 'captureOwnerStack' directly. Use 'if (process.env.NODE_ENV !== "production") {...}' to conditionally access it.`
|
|
1943
|
-
},
|
|
1944
|
-
schema: []
|
|
1945
|
-
},
|
|
1946
|
-
name: RULE_NAME33,
|
|
1947
|
-
create: create33,
|
|
1948
|
-
defaultOptions: []
|
|
1949
|
-
});
|
|
1950
|
-
function create33(context) {
|
|
1951
|
-
if (!context.sourceCode.text.includes("captureOwnerStack")) return {};
|
|
1952
|
-
const { importSource } = getSettingsFromContext(context);
|
|
1953
|
-
return {
|
|
1954
|
-
CallExpression(node) {
|
|
1955
|
-
if (!ER25.isCaptureOwnerStackCall(context, node)) return;
|
|
1956
|
-
if (AST8.findParentNode(node, isDevelopmentOnlyCheck) == null) {
|
|
1957
|
-
context.report({
|
|
1958
|
-
messageId: "missingDevelopmentOnlyCheck",
|
|
1959
|
-
node
|
|
1960
|
-
});
|
|
1961
|
-
}
|
|
1962
|
-
},
|
|
1963
|
-
ImportDeclaration(node) {
|
|
1964
|
-
if (node.source.value !== importSource) return;
|
|
1965
|
-
for (const specifier of node.specifiers) {
|
|
1966
|
-
if (specifier.type !== AST_NODE_TYPES.ImportSpecifier) continue;
|
|
1967
|
-
if (specifier.imported.type !== AST_NODE_TYPES.Identifier) continue;
|
|
1968
|
-
if (specifier.imported.name === "captureOwnerStack") {
|
|
1969
|
-
context.report({
|
|
1970
|
-
messageId: "useNamespaceImport",
|
|
1971
|
-
node: specifier
|
|
1972
|
-
});
|
|
1973
|
-
}
|
|
1974
|
-
}
|
|
1975
|
-
}
|
|
1976
|
-
};
|
|
1977
|
-
}
|
|
1978
|
-
function isDevelopmentOnlyCheck(node) {
|
|
1979
|
-
if (node.type !== AST_NODE_TYPES.IfStatement) return false;
|
|
1980
|
-
if (AST8.isProcessEnvNodeEnvCompare(node.test, "!==", "production")) return true;
|
|
1981
|
-
return false;
|
|
1982
|
-
}
|
|
1983
|
-
var RULE_NAME34 = "no-nested-component-definitions";
|
|
1984
|
-
var RULE_FEATURES34 = [];
|
|
1985
|
-
var no_nested_component_definitions_default = createRule({
|
|
1986
|
-
meta: {
|
|
1987
|
-
type: "problem",
|
|
1988
|
-
docs: {
|
|
1989
|
-
description: "Disallow nesting component definitions inside other components.",
|
|
1990
|
-
[Symbol.for("rule_features")]: RULE_FEATURES34
|
|
1991
|
-
},
|
|
1992
|
-
messages: {
|
|
1993
|
-
noNestedComponentDefinitions: "Do not nest component definitions inside other components or props. {{suggestion}}"
|
|
1994
|
-
},
|
|
1995
|
-
schema: []
|
|
1996
|
-
},
|
|
1997
|
-
name: RULE_NAME34,
|
|
1998
|
-
create: create34,
|
|
1999
|
-
defaultOptions: []
|
|
2000
|
-
});
|
|
2001
|
-
function create34(context) {
|
|
2002
|
-
const hint = ER25.ComponentDetectionHint.SkipArrayMapArgument | ER25.ComponentDetectionHint.SkipNullLiteral | ER25.ComponentDetectionHint.SkipUndefined | ER25.ComponentDetectionHint.SkipBooleanLiteral | ER25.ComponentDetectionHint.SkipStringLiteral | ER25.ComponentDetectionHint.SkipNumberLiteral | ER25.ComponentDetectionHint.StrictLogical | ER25.ComponentDetectionHint.StrictConditional;
|
|
2003
|
-
const collector = ER25.useComponentCollector(context, { hint });
|
|
2004
|
-
const collectorLegacy = ER25.useComponentCollectorLegacy();
|
|
2005
|
-
return {
|
|
2006
|
-
...collector.listeners,
|
|
2007
|
-
...collectorLegacy.listeners,
|
|
2008
|
-
"Program:exit"(program) {
|
|
2009
|
-
const functionComponents = [
|
|
2010
|
-
...collector.ctx.getAllComponents(program).values()
|
|
2011
|
-
];
|
|
2012
|
-
const classComponents = [
|
|
2013
|
-
...collectorLegacy.ctx.getAllComponents(program).values()
|
|
2014
|
-
];
|
|
2015
|
-
const isFunctionComponent = (node) => {
|
|
2016
|
-
return AST8.isFunction(node) && functionComponents.some((component) => component.node === node);
|
|
2017
|
-
};
|
|
2018
|
-
const isClassComponent12 = (node) => {
|
|
2019
|
-
return AST8.isClass(node) && classComponents.some((component) => component.node === node);
|
|
2020
|
-
};
|
|
2021
|
-
for (const { name: name5, node: component } of functionComponents) {
|
|
2022
|
-
if (name5 == null) continue;
|
|
2023
|
-
if (ER25.isDirectValueOfRenderPropertyLoose(component)) continue;
|
|
2024
|
-
if (isInsideJSXAttributeValue(component)) {
|
|
2025
|
-
if (!ER25.isDeclaredInRenderPropLoose(component)) {
|
|
2026
|
-
context.report({
|
|
2027
|
-
messageId: "noNestedComponentDefinitions",
|
|
2028
|
-
node: component,
|
|
2029
|
-
data: {
|
|
2030
|
-
name: name5,
|
|
2031
|
-
suggestion: "Move it to the top level or pass it as a prop."
|
|
2032
|
-
}
|
|
2033
|
-
});
|
|
2034
|
-
}
|
|
2035
|
-
continue;
|
|
2036
|
-
}
|
|
2037
|
-
if (isInsideCreateElementProps(context, component)) {
|
|
2038
|
-
context.report({
|
|
2039
|
-
messageId: "noNestedComponentDefinitions",
|
|
2040
|
-
node: component,
|
|
2041
|
-
data: {
|
|
2042
|
-
name: name5,
|
|
2043
|
-
suggestion: "Move it to the top level or pass it as a prop."
|
|
2044
|
-
}
|
|
2045
|
-
});
|
|
2046
|
-
continue;
|
|
2047
|
-
}
|
|
2048
|
-
const parentComponent = AST8.findParentNode(component, isFunctionComponent);
|
|
2049
|
-
if (parentComponent != null && !ER25.isDirectValueOfRenderPropertyLoose(parentComponent)) {
|
|
2050
|
-
context.report({
|
|
2051
|
-
messageId: "noNestedComponentDefinitions",
|
|
2052
|
-
node: component,
|
|
2053
|
-
data: {
|
|
2054
|
-
name: name5,
|
|
2055
|
-
suggestion: component.parent.type === AST_NODE_TYPES.Property ? "Move it to the top level or pass it as a prop." : "Move it to the top level."
|
|
2056
|
-
}
|
|
2057
|
-
});
|
|
2058
|
-
continue;
|
|
2059
|
-
}
|
|
2060
|
-
if (ER25.isInsideRenderMethod(component)) {
|
|
2061
|
-
context.report({
|
|
2062
|
-
messageId: "noNestedComponentDefinitions",
|
|
2063
|
-
node: component,
|
|
2064
|
-
data: {
|
|
2065
|
-
name: name5,
|
|
2066
|
-
suggestion: "Move it to the top level."
|
|
2067
|
-
}
|
|
2068
|
-
});
|
|
2069
|
-
}
|
|
2070
|
-
}
|
|
2071
|
-
for (const { name: name5 = "unknown", node: component } of classComponents) {
|
|
2072
|
-
if (AST8.findParentNode(component, (n) => isClassComponent12(n) || isFunctionComponent(n)) == null) {
|
|
2073
|
-
continue;
|
|
2074
|
-
}
|
|
2075
|
-
context.report({
|
|
2076
|
-
messageId: "noNestedComponentDefinitions",
|
|
2077
|
-
node: component,
|
|
2078
|
-
data: {
|
|
2079
|
-
name: name5,
|
|
2080
|
-
suggestion: component.parent.type === AST_NODE_TYPES.Property ? "Move it to the top level or pass it as a prop." : "Move it to the top level."
|
|
2081
|
-
}
|
|
2082
|
-
});
|
|
2083
|
-
}
|
|
2084
|
-
}
|
|
2085
|
-
};
|
|
2086
|
-
}
|
|
2087
|
-
function isInsideJSXAttributeValue(node) {
|
|
2088
|
-
return node.parent.type === AST_NODE_TYPES.JSXAttribute || ER25.findParentAttribute(node, (n) => n.value?.type === AST_NODE_TYPES.JSXExpressionContainer) != null;
|
|
2089
|
-
}
|
|
2090
|
-
function isInsideCreateElementProps(context, node) {
|
|
2091
|
-
const call = AST8.findParentNode(node, ER25.isCreateElementCall(context));
|
|
2092
|
-
if (call == null) return false;
|
|
2093
|
-
const prop = AST8.findParentNode(node, AST8.is(AST_NODE_TYPES.ObjectExpression));
|
|
2094
|
-
if (prop == null) return false;
|
|
2095
|
-
return prop === call.arguments[1];
|
|
2096
|
-
}
|
|
2097
|
-
var RULE_NAME35 = "no-nested-component-definitions";
|
|
2098
|
-
var RULE_FEATURES35 = [];
|
|
2099
|
-
var no_nested_lazy_component_declarations_default = createRule({
|
|
2100
|
-
meta: {
|
|
2101
|
-
type: "problem",
|
|
2102
|
-
docs: {
|
|
2103
|
-
description: "Disallow nesting lazy component declarations inside other components.",
|
|
2104
|
-
[Symbol.for("rule_features")]: RULE_FEATURES35
|
|
2105
|
-
},
|
|
2106
|
-
messages: {
|
|
2107
|
-
noNestedComponentDefinitions: "Do not declare lazy components inside other components. Instead, always declare them at the top level of your module."
|
|
2108
|
-
},
|
|
2109
|
-
schema: []
|
|
2110
|
-
},
|
|
2111
|
-
name: RULE_NAME35,
|
|
2112
|
-
create: create35,
|
|
2113
|
-
defaultOptions: []
|
|
2114
|
-
});
|
|
2115
|
-
function create35(context) {
|
|
2116
|
-
const hint = ER25.ComponentDetectionHint.None;
|
|
2117
|
-
const collector = ER25.useComponentCollector(context, { hint });
|
|
2118
|
-
const collectorLegacy = ER25.useComponentCollectorLegacy();
|
|
2119
|
-
const lazyComponentDeclarations = /* @__PURE__ */ new Set();
|
|
2120
|
-
return {
|
|
2121
|
-
...collector.listeners,
|
|
2122
|
-
...collectorLegacy.listeners,
|
|
2123
|
-
ImportExpression(node) {
|
|
2124
|
-
const lazyCall = AST8.findParentNode(node, (n) => ER25.isLazyCall(context, n));
|
|
2125
|
-
if (lazyCall != null) {
|
|
2126
|
-
lazyComponentDeclarations.add(lazyCall);
|
|
2127
|
-
}
|
|
2128
|
-
},
|
|
2129
|
-
"Program:exit"(program) {
|
|
2130
|
-
const functionComponents = [
|
|
2131
|
-
...collector.ctx.getAllComponents(program).values()
|
|
2132
|
-
];
|
|
2133
|
-
const classComponents = [
|
|
2134
|
-
...collectorLegacy.ctx.getAllComponents(program).values()
|
|
2135
|
-
];
|
|
2136
|
-
for (const lazy of lazyComponentDeclarations) {
|
|
2137
|
-
const significantParent = AST8.findParentNode(lazy, (n) => {
|
|
2138
|
-
if (AST8.isJSX(n)) return true;
|
|
2139
|
-
if (n.type === AST_NODE_TYPES.CallExpression) {
|
|
2140
|
-
return ER25.isReactHookCall(n) || ER25.isCreateElementCall(context, n) || ER25.isCreateContextCall(context, n);
|
|
2141
|
-
}
|
|
2142
|
-
if (AST8.isFunction(n)) {
|
|
2143
|
-
return functionComponents.some((c) => c.node === n);
|
|
2144
|
-
}
|
|
2145
|
-
if (AST8.isClass(n)) {
|
|
2146
|
-
return classComponents.some((c) => c.node === n);
|
|
2147
|
-
}
|
|
2148
|
-
return false;
|
|
2149
|
-
});
|
|
2150
|
-
if (significantParent != null) {
|
|
2151
|
-
context.report({
|
|
2152
|
-
messageId: "noNestedComponentDefinitions",
|
|
2153
|
-
node: lazy
|
|
2154
|
-
});
|
|
2155
|
-
}
|
|
2156
|
-
}
|
|
2157
|
-
}
|
|
2158
|
-
};
|
|
2159
|
-
}
|
|
2160
|
-
var RULE_NAME36 = "no-prop-types";
|
|
2161
|
-
var RULE_FEATURES36 = [];
|
|
2162
|
-
var no_prop_types_default = createRule({
|
|
2163
|
-
meta: {
|
|
2164
|
-
type: "problem",
|
|
2165
|
-
docs: {
|
|
2166
|
-
description: "Disallow `propTypes` in favor of TypeScript or another type-checking solution.",
|
|
2167
|
-
[Symbol.for("rule_features")]: RULE_FEATURES36
|
|
2168
|
-
},
|
|
2169
|
-
messages: {
|
|
2170
|
-
noPropTypes: "[Deprecated] Use TypeScript or another type-checking solution instead."
|
|
2171
|
-
},
|
|
2172
|
-
schema: []
|
|
2173
|
-
},
|
|
2174
|
-
name: RULE_NAME36,
|
|
2175
|
-
create: create36,
|
|
2176
|
-
defaultOptions: []
|
|
2177
|
-
});
|
|
2178
|
-
function create36(context) {
|
|
2179
|
-
if (!context.sourceCode.text.includes("propTypes")) {
|
|
2180
|
-
return {};
|
|
2181
|
-
}
|
|
2182
|
-
return {
|
|
2183
|
-
AssignmentExpression(node) {
|
|
2184
|
-
if (node.operator !== "=" || node.left.type !== AST_NODE_TYPES.MemberExpression) {
|
|
2185
|
-
return;
|
|
2186
|
-
}
|
|
2187
|
-
const { object, property } = node.left;
|
|
2188
|
-
if (object.type !== AST_NODE_TYPES.Identifier) {
|
|
2189
|
-
return;
|
|
2190
|
-
}
|
|
2191
|
-
if (property.type !== AST_NODE_TYPES.Identifier || property.name !== "propTypes") {
|
|
2192
|
-
return;
|
|
2193
|
-
}
|
|
2194
|
-
if (!ER25.isComponentNameLoose(object.name)) {
|
|
2195
|
-
return;
|
|
2196
|
-
}
|
|
2197
|
-
const variable = VAR2.findVariable(object.name, context.sourceCode.getScope(node));
|
|
2198
|
-
const variableNode = VAR2.getVariableInitNode(variable, 0);
|
|
2199
|
-
if (variableNode != null && (AST8.isFunction(variableNode) || ER25.isClassComponent(variableNode))) {
|
|
2200
|
-
context.report({ messageId: "noPropTypes", node: property });
|
|
2201
|
-
}
|
|
2202
|
-
},
|
|
2203
|
-
PropertyDefinition(node) {
|
|
2204
|
-
if (!ER25.isClassComponent(node.parent.parent)) {
|
|
2205
|
-
return;
|
|
2206
|
-
}
|
|
2207
|
-
if (!node.static || node.key.type !== AST_NODE_TYPES.Identifier || node.key.name !== "propTypes") {
|
|
2208
|
-
return;
|
|
2209
|
-
}
|
|
2210
|
-
context.report({ messageId: "noPropTypes", node });
|
|
2211
|
-
}
|
|
2212
|
-
};
|
|
2213
|
-
}
|
|
2214
|
-
var RULE_NAME37 = "no-redundant-should-component-update";
|
|
2215
|
-
var RULE_FEATURES37 = [];
|
|
2216
|
-
function isShouldComponentUpdate(node) {
|
|
2217
|
-
return AST8.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "shouldComponentUpdate";
|
|
2218
|
-
}
|
|
2219
|
-
var no_redundant_should_component_update_default = createRule({
|
|
2220
|
-
meta: {
|
|
2221
|
-
type: "problem",
|
|
2222
|
-
docs: {
|
|
2223
|
-
description: "Disallow `shouldComponentUpdate` when extending `React.PureComponent`.",
|
|
2224
|
-
[Symbol.for("rule_features")]: RULE_FEATURES37
|
|
2225
|
-
},
|
|
2226
|
-
messages: {
|
|
2227
|
-
noRedundantShouldComponentUpdate: "'{{componentName}}' does not need 'shouldComponentUpdate' when extending 'React.PureComponent'."
|
|
2228
|
-
},
|
|
2229
|
-
schema: []
|
|
2230
|
-
},
|
|
2231
|
-
name: RULE_NAME37,
|
|
2232
|
-
create: create37,
|
|
2233
|
-
defaultOptions: []
|
|
2234
|
-
});
|
|
2235
|
-
function create37(context) {
|
|
2236
|
-
if (!context.sourceCode.text.includes("shouldComponentUpdate")) return {};
|
|
2237
|
-
const { ctx, listeners } = ER25.useComponentCollectorLegacy();
|
|
2238
|
-
return {
|
|
2239
|
-
...listeners,
|
|
2240
|
-
"Program:exit"(program) {
|
|
2241
|
-
const components = ctx.getAllComponents(program);
|
|
2242
|
-
for (const { name: name5 = "PureComponent", node: component, flag } of components.values()) {
|
|
2243
|
-
if ((flag & ER25.ComponentFlag.PureComponent) === 0n) {
|
|
2244
|
-
continue;
|
|
2245
|
-
}
|
|
2246
|
-
const { body } = component.body;
|
|
2247
|
-
for (const member of body) {
|
|
2248
|
-
if (isShouldComponentUpdate(member)) {
|
|
2249
|
-
context.report({
|
|
2250
|
-
messageId: "noRedundantShouldComponentUpdate",
|
|
2251
|
-
node: member,
|
|
2252
|
-
data: {
|
|
2253
|
-
componentName: name5
|
|
2254
|
-
}
|
|
2255
|
-
});
|
|
2256
|
-
}
|
|
2257
|
-
}
|
|
2258
|
-
}
|
|
2259
|
-
}
|
|
2260
|
-
};
|
|
2261
|
-
}
|
|
2262
|
-
var RULE_NAME38 = "no-set-state-in-component-did-mount";
|
|
2263
|
-
var RULE_FEATURES38 = [];
|
|
2264
|
-
var no_set_state_in_component_did_mount_default = createRule({
|
|
2265
|
-
meta: {
|
|
2266
|
-
type: "problem",
|
|
2267
|
-
docs: {
|
|
2268
|
-
description: "Disallow calling `this.setState` in `componentDidMount` outside of functions, such as callbacks.",
|
|
2269
|
-
[Symbol.for("rule_features")]: RULE_FEATURES38
|
|
2270
|
-
},
|
|
2271
|
-
messages: {
|
|
2272
|
-
noSetStateInComponentDidMount: "Do not call `this.setState` in `componentDidMount` outside of functions, such as callbacks."
|
|
2273
|
-
},
|
|
2274
|
-
schema: []
|
|
2275
|
-
},
|
|
2276
|
-
name: RULE_NAME38,
|
|
2277
|
-
create: create38,
|
|
2278
|
-
defaultOptions: []
|
|
2279
|
-
});
|
|
2280
|
-
function create38(context) {
|
|
2281
|
-
if (!context.sourceCode.text.includes("componentDidMount")) return {};
|
|
2282
|
-
return {
|
|
2283
|
-
CallExpression(node) {
|
|
2284
|
-
if (!ER25.isThisSetState(node)) {
|
|
2285
|
-
return;
|
|
2286
|
-
}
|
|
2287
|
-
const clazz = AST8.findParentNode(node, ER25.isClassComponent);
|
|
2288
|
-
const method = AST8.findParentNode(node, (n) => n === clazz || ER25.isComponentDidMount(n));
|
|
2289
|
-
if (clazz == null || method == null || method === clazz) return;
|
|
2290
|
-
const methodScope = context.sourceCode.getScope(method);
|
|
2291
|
-
const upperScope = context.sourceCode.getScope(node).upper;
|
|
2292
|
-
if (method.parent === clazz.body && upperScope === methodScope) {
|
|
2293
|
-
context.report({
|
|
2294
|
-
messageId: "noSetStateInComponentDidMount",
|
|
2295
|
-
node
|
|
2296
|
-
});
|
|
2297
|
-
}
|
|
2298
|
-
}
|
|
2299
|
-
};
|
|
2300
|
-
}
|
|
2301
|
-
var RULE_NAME39 = "no-set-state-in-component-did-update";
|
|
2302
|
-
var RULE_FEATURES39 = [];
|
|
2303
|
-
var no_set_state_in_component_did_update_default = createRule({
|
|
2304
|
-
meta: {
|
|
2305
|
-
type: "problem",
|
|
2306
|
-
docs: {
|
|
2307
|
-
description: "Disallow calling `this.setState` in `componentDidUpdate` outside of functions, such as callbacks.",
|
|
2308
|
-
[Symbol.for("rule_features")]: RULE_FEATURES39
|
|
2309
|
-
},
|
|
2310
|
-
messages: {
|
|
2311
|
-
noSetStateInComponentDidUpdate: "Do not call `this.setState` in `componentDidUpdate` outside of functions, such as callbacks."
|
|
2312
|
-
},
|
|
2313
|
-
schema: []
|
|
2314
|
-
},
|
|
2315
|
-
name: RULE_NAME39,
|
|
2316
|
-
create: create39,
|
|
2317
|
-
defaultOptions: []
|
|
2318
|
-
});
|
|
2319
|
-
function create39(context) {
|
|
2320
|
-
if (!context.sourceCode.text.includes("componentDidUpdate")) return {};
|
|
2321
|
-
return {
|
|
2322
|
-
CallExpression(node) {
|
|
2323
|
-
if (!ER25.isThisSetState(node)) {
|
|
2324
|
-
return;
|
|
2325
|
-
}
|
|
2326
|
-
const clazz = AST8.findParentNode(node, ER25.isClassComponent);
|
|
2327
|
-
const method = AST8.findParentNode(node, (n) => n === clazz || ER25.isComponentDidUpdate(n));
|
|
2328
|
-
if (clazz == null || method == null || method === clazz) return;
|
|
2329
|
-
const methodScope = context.sourceCode.getScope(method);
|
|
2330
|
-
const upperScope = context.sourceCode.getScope(node).upper;
|
|
2331
|
-
if (method.parent === clazz.body && upperScope === methodScope) {
|
|
2332
|
-
context.report({
|
|
2333
|
-
messageId: "noSetStateInComponentDidUpdate",
|
|
2334
|
-
node
|
|
2335
|
-
});
|
|
2336
|
-
}
|
|
2337
|
-
}
|
|
2338
|
-
};
|
|
2339
|
-
}
|
|
2340
|
-
var RULE_NAME40 = "no-set-state-in-component-will-update";
|
|
2341
|
-
var RULE_FEATURES40 = [];
|
|
2342
|
-
var no_set_state_in_component_will_update_default = createRule({
|
|
2343
|
-
meta: {
|
|
2344
|
-
type: "problem",
|
|
2345
|
-
docs: {
|
|
2346
|
-
description: "Disallows calling `this.setState` in `componentWillUpdate` outside of functions, such as callbacks.",
|
|
2347
|
-
[Symbol.for("rule_features")]: RULE_FEATURES40
|
|
2348
|
-
},
|
|
2349
|
-
messages: {
|
|
2350
|
-
noSetStateInComponentWillUpdate: "Do not call `this.setState` in `componentWillUpdate` outside of functions, such as callbacks."
|
|
2351
|
-
},
|
|
2352
|
-
schema: []
|
|
2353
|
-
},
|
|
2354
|
-
name: RULE_NAME40,
|
|
2355
|
-
create: create40,
|
|
2356
|
-
defaultOptions: []
|
|
2357
|
-
});
|
|
2358
|
-
function create40(context) {
|
|
2359
|
-
if (!context.sourceCode.text.includes("componentWillUpdate")) return {};
|
|
2360
|
-
return {
|
|
2361
|
-
CallExpression(node) {
|
|
2362
|
-
if (!ER25.isThisSetState(node)) {
|
|
2363
|
-
return;
|
|
2364
|
-
}
|
|
2365
|
-
const clazz = AST8.findParentNode(node, ER25.isClassComponent);
|
|
2366
|
-
const method = AST8.findParentNode(node, (n) => n === clazz || ER25.isComponentWillUpdate(n));
|
|
2367
|
-
if (clazz == null || method == null || method === clazz) return;
|
|
2368
|
-
const methodScope = context.sourceCode.getScope(method);
|
|
2369
|
-
const upperScope = context.sourceCode.getScope(node).upper;
|
|
2370
|
-
if (method.parent === clazz.body && upperScope === methodScope) {
|
|
2371
|
-
context.report({
|
|
2372
|
-
messageId: "noSetStateInComponentWillUpdate",
|
|
2373
|
-
node
|
|
2374
|
-
});
|
|
2375
|
-
}
|
|
2376
|
-
}
|
|
2377
|
-
};
|
|
2378
|
-
}
|
|
2379
|
-
var RULE_NAME41 = "no-string-refs";
|
|
2380
|
-
var RULE_FEATURES41 = [
|
|
2381
|
-
"MOD"
|
|
2382
|
-
];
|
|
2383
|
-
var no_string_refs_default = createRule({
|
|
2384
|
-
meta: {
|
|
2385
|
-
type: "problem",
|
|
2386
|
-
docs: {
|
|
2387
|
-
description: "Replaces string refs with callback refs.",
|
|
2388
|
-
[Symbol.for("rule_features")]: RULE_FEATURES41
|
|
2389
|
-
},
|
|
2390
|
-
fixable: "code",
|
|
2391
|
-
messages: {
|
|
2392
|
-
noStringRefs: "[Deprecated] Use callback refs instead."
|
|
2393
|
-
},
|
|
2394
|
-
schema: []
|
|
2395
|
-
},
|
|
2396
|
-
name: RULE_NAME41,
|
|
2397
|
-
create: create41,
|
|
2398
|
-
defaultOptions: []
|
|
2399
|
-
});
|
|
2400
|
-
function create41(context) {
|
|
2401
|
-
const state = {
|
|
2402
|
-
isWithinClassComponent: false
|
|
2403
|
-
};
|
|
2404
|
-
function onClassBodyEnter(node) {
|
|
2405
|
-
if (ER25.isClassComponent(node.parent)) {
|
|
2406
|
-
state.isWithinClassComponent = true;
|
|
2407
|
-
}
|
|
2408
|
-
}
|
|
2409
|
-
function onClassBodyExit() {
|
|
2410
|
-
state.isWithinClassComponent = false;
|
|
2411
|
-
}
|
|
2412
|
-
return {
|
|
2413
|
-
ClassBody: onClassBodyEnter,
|
|
2414
|
-
"ClassBody:exit": onClassBodyExit,
|
|
2415
|
-
JSXAttribute(node) {
|
|
2416
|
-
if (node.name.name !== "ref") return;
|
|
2417
|
-
const refNameText = getAttributeValueText(context, node.value);
|
|
2418
|
-
if (refNameText == null) return;
|
|
2419
|
-
context.report({
|
|
2420
|
-
messageId: "noStringRefs",
|
|
2421
|
-
node,
|
|
2422
|
-
fix(fixer) {
|
|
2423
|
-
if (node.value == null) return null;
|
|
2424
|
-
if (!state.isWithinClassComponent) return null;
|
|
2425
|
-
return fixer.replaceText(node.value, `{(ref) => { this.refs[${refNameText}] = ref; }}`);
|
|
2426
|
-
}
|
|
2427
|
-
});
|
|
2428
|
-
}
|
|
2429
|
-
};
|
|
2430
|
-
}
|
|
2431
|
-
function getAttributeValueText(context, node) {
|
|
2432
|
-
if (node == null) return null;
|
|
2433
|
-
switch (true) {
|
|
2434
|
-
case (node.type === AST_NODE_TYPES.Literal && typeof node.value === "string"):
|
|
2435
|
-
return context.sourceCode.getText(node);
|
|
2436
|
-
case (node.type === AST_NODE_TYPES.JSXExpressionContainer && node.expression.type === AST_NODE_TYPES.Literal && typeof node.expression.value === "string"):
|
|
2437
|
-
return context.sourceCode.getText(node.expression);
|
|
2438
|
-
case (node.type === AST_NODE_TYPES.JSXExpressionContainer && node.expression.type === AST_NODE_TYPES.TemplateLiteral):
|
|
2439
|
-
return context.sourceCode.getText(node.expression);
|
|
2440
|
-
default:
|
|
2441
|
-
return null;
|
|
2442
|
-
}
|
|
2443
|
-
}
|
|
2444
|
-
var RULE_NAME42 = "no-unsafe-component-will-mount";
|
|
2445
|
-
var RULE_FEATURES42 = [];
|
|
2446
|
-
function isUnsafeComponentWillMount(node) {
|
|
2447
|
-
return AST8.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "UNSAFE_componentWillMount";
|
|
2448
|
-
}
|
|
2449
|
-
var no_unsafe_component_will_mount_default = createRule({
|
|
2450
|
-
meta: {
|
|
2451
|
-
type: "problem",
|
|
2452
|
-
docs: {
|
|
2453
|
-
description: "Warns the usage of `UNSAFE_componentWillMount` in class components.",
|
|
2454
|
-
[Symbol.for("rule_features")]: RULE_FEATURES42
|
|
2455
|
-
},
|
|
2456
|
-
messages: {
|
|
2457
|
-
noUnsafeComponentWillMount: "Do not use 'UNSAFE_componentWillMount'."
|
|
2458
|
-
},
|
|
2459
|
-
schema: []
|
|
2460
|
-
},
|
|
2461
|
-
name: RULE_NAME42,
|
|
2462
|
-
create: create42,
|
|
2463
|
-
defaultOptions: []
|
|
2464
|
-
});
|
|
2465
|
-
function create42(context) {
|
|
2466
|
-
if (!context.sourceCode.text.includes("UNSAFE_componentWillMount")) return {};
|
|
2467
|
-
const { ctx, listeners } = ER25.useComponentCollectorLegacy();
|
|
2468
|
-
return {
|
|
2469
|
-
...listeners,
|
|
2470
|
-
"Program:exit"(program) {
|
|
2471
|
-
const components = ctx.getAllComponents(program);
|
|
2472
|
-
for (const { node: component } of components.values()) {
|
|
2473
|
-
const { body } = component.body;
|
|
2474
|
-
for (const member of body) {
|
|
2475
|
-
if (isUnsafeComponentWillMount(member)) {
|
|
2476
|
-
context.report({
|
|
2477
|
-
messageId: "noUnsafeComponentWillMount",
|
|
2478
|
-
node: member
|
|
2479
|
-
});
|
|
2480
|
-
}
|
|
2481
|
-
}
|
|
2482
|
-
}
|
|
2483
|
-
}
|
|
2484
|
-
};
|
|
2485
|
-
}
|
|
2486
|
-
var RULE_NAME43 = "no-unsafe-component-will-receive-props";
|
|
2487
|
-
var RULE_FEATURES43 = [];
|
|
2488
|
-
function isUnsafeComponentWillReceiveProps(node) {
|
|
2489
|
-
return AST8.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "UNSAFE_componentWillReceiveProps";
|
|
2490
|
-
}
|
|
2491
|
-
var no_unsafe_component_will_receive_props_default = createRule({
|
|
2492
|
-
meta: {
|
|
2493
|
-
type: "problem",
|
|
2494
|
-
docs: {
|
|
2495
|
-
description: "Warns the usage of `UNSAFE_componentWillReceiveProps` in class components.",
|
|
2496
|
-
[Symbol.for("rule_features")]: RULE_FEATURES43
|
|
2497
|
-
},
|
|
2498
|
-
messages: {
|
|
2499
|
-
noUnsafeComponentWillReceiveProps: "Do not use 'UNSAFE_componentWillReceiveProps'."
|
|
2500
|
-
},
|
|
2501
|
-
schema: []
|
|
2502
|
-
},
|
|
2503
|
-
name: RULE_NAME43,
|
|
2504
|
-
create: create43,
|
|
2505
|
-
defaultOptions: []
|
|
2506
|
-
});
|
|
2507
|
-
function create43(context) {
|
|
2508
|
-
if (!context.sourceCode.text.includes("UNSAFE_componentWillReceiveProps")) {
|
|
2509
|
-
return {};
|
|
2510
|
-
}
|
|
2511
|
-
const { ctx, listeners } = ER25.useComponentCollectorLegacy();
|
|
2512
|
-
return {
|
|
2513
|
-
...listeners,
|
|
2514
|
-
"Program:exit"(program) {
|
|
2515
|
-
const components = ctx.getAllComponents(program);
|
|
2516
|
-
for (const { node: component } of components.values()) {
|
|
2517
|
-
const { body } = component.body;
|
|
2518
|
-
for (const member of body) {
|
|
2519
|
-
if (isUnsafeComponentWillReceiveProps(member)) {
|
|
2520
|
-
context.report({
|
|
2521
|
-
messageId: "noUnsafeComponentWillReceiveProps",
|
|
2522
|
-
node: member
|
|
2523
|
-
});
|
|
2524
|
-
}
|
|
2525
|
-
}
|
|
2526
|
-
}
|
|
2527
|
-
}
|
|
2528
|
-
};
|
|
2529
|
-
}
|
|
2530
|
-
var RULE_NAME44 = "no-unsafe-component-will-update";
|
|
2531
|
-
var RULE_FEATURES44 = [];
|
|
2532
|
-
function isUnsafeComponentWillUpdate(node) {
|
|
2533
|
-
return AST8.isMethodOrProperty(node) && node.key.type === AST_NODE_TYPES.Identifier && node.key.name === "UNSAFE_componentWillUpdate";
|
|
2534
|
-
}
|
|
2535
|
-
var no_unsafe_component_will_update_default = createRule({
|
|
2536
|
-
meta: {
|
|
2537
|
-
type: "problem",
|
|
2538
|
-
docs: {
|
|
2539
|
-
description: "Warns the usage of `UNSAFE_componentWillUpdate` in class components.",
|
|
2540
|
-
[Symbol.for("rule_features")]: RULE_FEATURES44
|
|
2541
|
-
},
|
|
2542
|
-
messages: {
|
|
2543
|
-
noUnsafeComponentWillUpdate: "Do not use 'UNSAFE_componentWillUpdate'."
|
|
2544
|
-
},
|
|
2545
|
-
schema: []
|
|
2546
|
-
},
|
|
2547
|
-
name: RULE_NAME44,
|
|
2548
|
-
create: create44,
|
|
2549
|
-
defaultOptions: []
|
|
2550
|
-
});
|
|
2551
|
-
function create44(context) {
|
|
2552
|
-
if (!context.sourceCode.text.includes("UNSAFE_componentWillUpdate")) return {};
|
|
2553
|
-
const { ctx, listeners } = ER25.useComponentCollectorLegacy();
|
|
2554
|
-
return {
|
|
2555
|
-
...listeners,
|
|
2556
|
-
"Program:exit"(program) {
|
|
2557
|
-
const components = ctx.getAllComponents(program);
|
|
2558
|
-
for (const { node: component } of components.values()) {
|
|
2559
|
-
const { body } = component.body;
|
|
2560
|
-
for (const member of body) {
|
|
2561
|
-
if (isUnsafeComponentWillUpdate(member)) {
|
|
2562
|
-
context.report({
|
|
2563
|
-
messageId: "noUnsafeComponentWillUpdate",
|
|
2564
|
-
node: member
|
|
2565
|
-
});
|
|
2566
|
-
}
|
|
2567
|
-
}
|
|
2568
|
-
}
|
|
2569
|
-
}
|
|
2570
|
-
};
|
|
2571
|
-
}
|
|
2572
|
-
var RULE_NAME45 = "no-unstable-context-value";
|
|
2573
|
-
var RULE_FEATURES45 = [];
|
|
2574
|
-
var no_unstable_context_value_default = createRule({
|
|
2575
|
-
meta: {
|
|
2576
|
-
type: "problem",
|
|
2577
|
-
docs: {
|
|
2578
|
-
description: "Prevents non-stable values (i.e. object literals) from being used as a value for `Context.Provider`.",
|
|
2579
|
-
[Symbol.for("rule_features")]: RULE_FEATURES45
|
|
2580
|
-
},
|
|
2581
|
-
messages: {
|
|
2582
|
-
unstableContextValue: "A/an '{{type}}' passed as the value prop to the context provider should not be constructed. It will change on every render. {{suggestion}}"
|
|
2583
|
-
},
|
|
2584
|
-
schema: []
|
|
2585
|
-
},
|
|
2586
|
-
name: RULE_NAME45,
|
|
2587
|
-
create: create45,
|
|
2588
|
-
defaultOptions: []
|
|
2589
|
-
});
|
|
2590
|
-
function create45(context) {
|
|
2591
|
-
const { version: version2 } = getSettingsFromContext(context);
|
|
2592
|
-
const isReact18OrBelow = compare(version2, "19.0.0", "<");
|
|
2593
|
-
const { ctx, listeners } = ER25.useComponentCollector(context);
|
|
2594
|
-
const constructions = /* @__PURE__ */ new WeakMap();
|
|
2595
|
-
return {
|
|
2596
|
-
...listeners,
|
|
2597
|
-
JSXOpeningElement(node) {
|
|
2598
|
-
const fullName = ER25.getElementType(context, node.parent);
|
|
2599
|
-
const selfName = fullName.split(".").at(-1);
|
|
2600
|
-
if (selfName == null) return;
|
|
2601
|
-
if (!isContextName(selfName, isReact18OrBelow)) return;
|
|
2602
|
-
const functionEntry = ctx.getCurrentEntry();
|
|
2603
|
-
if (functionEntry == null) return;
|
|
2604
|
-
const attribute = node.attributes.find(
|
|
2605
|
-
(attribute2) => attribute2.type === AST_NODE_TYPES.JSXAttribute && attribute2.name.name === "value"
|
|
2606
|
-
);
|
|
2607
|
-
if (attribute == null || !("value" in attribute)) return;
|
|
2608
|
-
const value = attribute.value;
|
|
2609
|
-
if (value?.type !== AST_NODE_TYPES.JSXExpressionContainer) return;
|
|
2610
|
-
const valueExpression = value.expression;
|
|
2611
|
-
const initialScope = context.sourceCode.getScope(valueExpression);
|
|
2612
|
-
const construction = VAR2.getConstruction(valueExpression, initialScope);
|
|
2613
|
-
if (construction == null) return;
|
|
2614
|
-
if (ER25.isReactHookCall(construction.node)) {
|
|
2615
|
-
return;
|
|
2616
|
-
}
|
|
2617
|
-
getOrElseUpdate(constructions, functionEntry.node, () => []).push(construction);
|
|
2618
|
-
},
|
|
2619
|
-
"Program:exit"(program) {
|
|
2620
|
-
const components = ctx.getAllComponents(program).values();
|
|
2621
|
-
for (const { node: component } of components) {
|
|
2622
|
-
for (const construction of constructions.get(component) ?? []) {
|
|
2623
|
-
const { kind, node: constructionNode } = construction;
|
|
2624
|
-
const suggestion = kind.startsWith("Function") ? "Consider wrapping it in a useCallback hook." : "Consider wrapping it in a useMemo hook.";
|
|
2625
|
-
context.report({
|
|
2626
|
-
messageId: "unstableContextValue",
|
|
2627
|
-
node: constructionNode,
|
|
2628
|
-
data: {
|
|
2629
|
-
type: AST8.toDelimiterCaseType(constructionNode),
|
|
2630
|
-
suggestion
|
|
2631
|
-
}
|
|
2632
|
-
});
|
|
2633
|
-
}
|
|
2634
|
-
}
|
|
2635
|
-
}
|
|
2636
|
-
};
|
|
2637
|
-
}
|
|
2638
|
-
function isContextName(name5, isReact18OrBelow) {
|
|
2639
|
-
if (name5 === "Provider") return true;
|
|
2640
|
-
if (!isReact18OrBelow) {
|
|
2641
|
-
return name5.endsWith("Context") || name5.endsWith("CONTEXT");
|
|
2642
|
-
}
|
|
2643
|
-
return false;
|
|
2644
|
-
}
|
|
2645
|
-
var RULE_NAME46 = "no-unstable-default-props";
|
|
2646
|
-
var RULE_FEATURES46 = [];
|
|
2647
|
-
var no_unstable_default_props_default = createRule({
|
|
2648
|
-
meta: {
|
|
2649
|
-
type: "problem",
|
|
2650
|
-
docs: {
|
|
2651
|
-
description: "Prevents using referential-type values as default props in object destructuring.",
|
|
2652
|
-
[Symbol.for("rule_features")]: RULE_FEATURES46
|
|
2653
|
-
},
|
|
2654
|
-
messages: {
|
|
2655
|
-
noUnstableDefaultProps: "A/an '{{forbiddenType}}' as default prop. This could lead to potential infinite render loop in React. Use a variable instead of '{{forbiddenType}}'."
|
|
2656
|
-
},
|
|
2657
|
-
schema: []
|
|
2658
|
-
},
|
|
2659
|
-
name: RULE_NAME46,
|
|
2660
|
-
create: create46,
|
|
2661
|
-
defaultOptions: []
|
|
2662
|
-
});
|
|
2663
|
-
function create46(context) {
|
|
2664
|
-
const { ctx, listeners } = ER25.useComponentCollector(context);
|
|
2665
|
-
const declarators = /* @__PURE__ */ new WeakMap();
|
|
2666
|
-
return {
|
|
2667
|
-
...listeners,
|
|
2668
|
-
"Program:exit"(program) {
|
|
2669
|
-
const components = ctx.getAllComponents(program);
|
|
2670
|
-
for (const { node: component } of components.values()) {
|
|
2671
|
-
const { params } = component;
|
|
2672
|
-
const [props] = params;
|
|
2673
|
-
if (props == null) {
|
|
2674
|
-
continue;
|
|
2675
|
-
}
|
|
2676
|
-
const properties = match(props).with({ type: AST_NODE_TYPES.ObjectPattern }, ({ properties: properties2 }) => properties2).with({ type: AST_NODE_TYPES.Identifier }, ({ name: name5 }) => {
|
|
2677
|
-
return declarators.get(component)?.filter((d) => d.init.name === name5).flatMap((d) => d.id.properties) ?? [];
|
|
2678
|
-
}).otherwise(() => []);
|
|
2679
|
-
for (const prop of properties) {
|
|
2680
|
-
if (prop.type !== AST_NODE_TYPES.Property || prop.value.type !== AST_NODE_TYPES.AssignmentPattern) {
|
|
2681
|
-
continue;
|
|
2682
|
-
}
|
|
2683
|
-
const { value } = prop;
|
|
2684
|
-
const { right } = value;
|
|
2685
|
-
const initialScope = context.sourceCode.getScope(value);
|
|
2686
|
-
const construction = VAR2.getConstruction(
|
|
2687
|
-
value,
|
|
2688
|
-
initialScope,
|
|
2689
|
-
VAR2.ConstructionDetectionHint.StrictCallExpression
|
|
2690
|
-
);
|
|
2691
|
-
if (construction == null) {
|
|
2692
|
-
continue;
|
|
2693
|
-
}
|
|
2694
|
-
if (ER25.isReactHookCall(construction.node)) {
|
|
2695
|
-
continue;
|
|
2696
|
-
}
|
|
2697
|
-
const forbiddenType = AST8.toDelimiterCaseType(right);
|
|
2698
|
-
context.report({
|
|
2699
|
-
messageId: "noUnstableDefaultProps",
|
|
2700
|
-
node: right,
|
|
2701
|
-
data: {
|
|
2702
|
-
forbiddenType
|
|
2703
|
-
}
|
|
2704
|
-
});
|
|
2705
|
-
}
|
|
2706
|
-
}
|
|
2707
|
-
},
|
|
2708
|
-
[Selector.OBJECT_DESTRUCTURING_VARIABLE_DECLARATOR](node) {
|
|
2709
|
-
const functionEntry = ctx.getCurrentEntry();
|
|
2710
|
-
if (functionEntry == null) return;
|
|
2711
|
-
getOrElseUpdate(
|
|
2712
|
-
declarators,
|
|
2713
|
-
functionEntry.node,
|
|
2714
|
-
() => []
|
|
2715
|
-
).push(node);
|
|
2716
|
-
}
|
|
2717
|
-
};
|
|
2718
|
-
}
|
|
2719
|
-
var RULE_NAME47 = "no-unused-class-component-members";
|
|
2720
|
-
var RULE_FEATURES47 = [];
|
|
2721
|
-
var LIFECYCLE_METHODS = /* @__PURE__ */ new Set([
|
|
2722
|
-
"componentDidCatch",
|
|
2723
|
-
"componentDidMount",
|
|
2724
|
-
"componentDidUpdate",
|
|
2725
|
-
"componentWillMount",
|
|
2726
|
-
"componentWillReceiveProps",
|
|
2727
|
-
"componentWillUnmount",
|
|
2728
|
-
"componentWillUpdate",
|
|
2729
|
-
"constructor",
|
|
2730
|
-
"getSnapshotBeforeUpdate",
|
|
2731
|
-
"render",
|
|
2732
|
-
"shouldComponentUpdate",
|
|
2733
|
-
"state",
|
|
2734
|
-
"UNSAFE_componentWillMount",
|
|
2735
|
-
"UNSAFE_componentWillReceiveProps",
|
|
2736
|
-
"UNSAFE_componentWillUpdate"
|
|
2737
|
-
]);
|
|
2738
|
-
function isKeyLiteral2(node, key) {
|
|
2739
|
-
return match(key).with({ type: AST_NODE_TYPES.Literal }, constTrue).with({ type: AST_NODE_TYPES.TemplateLiteral, expressions: [] }, constTrue).with({ type: AST_NODE_TYPES.Identifier }, () => !node.computed).otherwise(constFalse);
|
|
2740
|
-
}
|
|
2741
|
-
var no_unused_class_component_members_default = createRule({
|
|
2742
|
-
meta: {
|
|
2743
|
-
type: "problem",
|
|
2744
|
-
docs: {
|
|
2745
|
-
description: "Warns unused class component methods and properties.",
|
|
2746
|
-
[Symbol.for("rule_features")]: RULE_FEATURES47
|
|
2747
|
-
},
|
|
2748
|
-
messages: {
|
|
2749
|
-
noUnusedClassComponentMembers: "Unused method or property '{{methodName}}'' of class '{{className}}'."
|
|
2750
|
-
},
|
|
2751
|
-
schema: []
|
|
2752
|
-
},
|
|
2753
|
-
name: RULE_NAME47,
|
|
2754
|
-
create: create47,
|
|
2755
|
-
defaultOptions: []
|
|
2756
|
-
});
|
|
2757
|
-
function create47(context) {
|
|
2758
|
-
const classEntries = [];
|
|
2759
|
-
const methodEntries = [];
|
|
2760
|
-
const propertyDefs = /* @__PURE__ */ new WeakMap();
|
|
2761
|
-
const propertyUsages = /* @__PURE__ */ new WeakMap();
|
|
2762
|
-
function classEnter(node) {
|
|
2763
|
-
classEntries.push(node);
|
|
2764
|
-
if (!ER25.isClassComponent(node)) {
|
|
2765
|
-
return;
|
|
2766
|
-
}
|
|
2767
|
-
propertyDefs.set(node, /* @__PURE__ */ new Set());
|
|
2768
|
-
propertyUsages.set(node, /* @__PURE__ */ new Set());
|
|
2769
|
-
}
|
|
2770
|
-
function classExit() {
|
|
2771
|
-
const currentClass = classEntries.pop();
|
|
2772
|
-
if (currentClass == null || !ER25.isClassComponent(currentClass)) {
|
|
2773
|
-
return;
|
|
2774
|
-
}
|
|
2775
|
-
const className = AST8.getClassId(currentClass)?.name;
|
|
2776
|
-
const defs = propertyDefs.get(currentClass);
|
|
2777
|
-
const usages = propertyUsages.get(currentClass);
|
|
2778
|
-
if (defs == null) {
|
|
2779
|
-
return;
|
|
2780
|
-
}
|
|
2781
|
-
for (const def of defs) {
|
|
2782
|
-
const methodName = AST8.getPropertyName(def);
|
|
2783
|
-
if (methodName == null) {
|
|
2784
|
-
continue;
|
|
2785
|
-
}
|
|
2786
|
-
if (usages?.has(methodName) || LIFECYCLE_METHODS.has(methodName)) {
|
|
2787
|
-
continue;
|
|
2788
|
-
}
|
|
2789
|
-
context.report({
|
|
2790
|
-
messageId: "noUnusedClassComponentMembers",
|
|
2791
|
-
node: def,
|
|
2792
|
-
data: {
|
|
2793
|
-
className: className ?? "Component",
|
|
2794
|
-
methodName
|
|
2795
|
-
}
|
|
2796
|
-
});
|
|
2797
|
-
}
|
|
2798
|
-
}
|
|
2799
|
-
function methodEnter(node) {
|
|
2800
|
-
methodEntries.push(node);
|
|
2801
|
-
const currentClass = classEntries.at(-1);
|
|
2802
|
-
if (currentClass == null || !ER25.isClassComponent(currentClass)) {
|
|
2803
|
-
return;
|
|
2804
|
-
}
|
|
2805
|
-
if (node.static) {
|
|
2806
|
-
return;
|
|
2807
|
-
}
|
|
2808
|
-
if (isKeyLiteral2(node, node.key)) {
|
|
2809
|
-
propertyDefs.get(currentClass)?.add(node.key);
|
|
2810
|
-
}
|
|
2811
|
-
}
|
|
2812
|
-
function methodExit() {
|
|
2813
|
-
methodEntries.pop();
|
|
2814
|
-
}
|
|
2815
|
-
return {
|
|
2816
|
-
ClassDeclaration: classEnter,
|
|
2817
|
-
"ClassDeclaration:exit": classExit,
|
|
2818
|
-
ClassExpression: classEnter,
|
|
2819
|
-
"ClassExpression:exit": classExit,
|
|
2820
|
-
MemberExpression(node) {
|
|
2821
|
-
const currentClass = classEntries.at(-1);
|
|
2822
|
-
const currentMethod = methodEntries.at(-1);
|
|
2823
|
-
if (currentClass == null || currentMethod == null) {
|
|
2824
|
-
return;
|
|
2825
|
-
}
|
|
2826
|
-
if (!ER25.isClassComponent(currentClass) || currentMethod.static) {
|
|
2827
|
-
return;
|
|
2828
|
-
}
|
|
2829
|
-
if (!AST8.isThisExpression(node.object) || !isKeyLiteral2(node, node.property)) {
|
|
2830
|
-
return;
|
|
2831
|
-
}
|
|
2832
|
-
if (node.parent.type === AST_NODE_TYPES.AssignmentExpression && node.parent.left === node) {
|
|
2833
|
-
propertyDefs.get(currentClass)?.add(node.property);
|
|
2834
|
-
return;
|
|
2835
|
-
}
|
|
2836
|
-
const propertyName = AST8.getPropertyName(node.property);
|
|
2837
|
-
if (propertyName != null) {
|
|
2838
|
-
propertyUsages.get(currentClass)?.add(propertyName);
|
|
2839
|
-
}
|
|
2840
|
-
},
|
|
2841
|
-
MethodDefinition: methodEnter,
|
|
2842
|
-
"MethodDefinition:exit": methodExit,
|
|
2843
|
-
PropertyDefinition: methodEnter,
|
|
2844
|
-
"PropertyDefinition:exit": methodExit,
|
|
2845
|
-
VariableDeclarator(node) {
|
|
2846
|
-
const currentClass = classEntries.at(-1);
|
|
2847
|
-
const currentMethod = methodEntries.at(-1);
|
|
2848
|
-
if (currentClass == null || currentMethod == null) {
|
|
2849
|
-
return;
|
|
2850
|
-
}
|
|
2851
|
-
if (!ER25.isClassComponent(currentClass) || currentMethod.static) {
|
|
2852
|
-
return;
|
|
2853
|
-
}
|
|
2854
|
-
if (node.init != null && AST8.isThisExpression(node.init) && node.id.type === AST_NODE_TYPES.ObjectPattern) {
|
|
2855
|
-
for (const prop of node.id.properties) {
|
|
2856
|
-
if (prop.type === AST_NODE_TYPES.Property && isKeyLiteral2(prop, prop.key)) {
|
|
2857
|
-
const keyName = AST8.getPropertyName(prop.key);
|
|
2858
|
-
if (keyName != null) {
|
|
2859
|
-
propertyUsages.get(currentClass)?.add(keyName);
|
|
2860
|
-
}
|
|
2861
|
-
}
|
|
2862
|
-
}
|
|
2863
|
-
}
|
|
2864
|
-
}
|
|
2865
|
-
};
|
|
2866
|
-
}
|
|
2867
|
-
var RULE_NAME48 = "no-unused-state";
|
|
2868
|
-
var RULE_FEATURES48 = [];
|
|
2869
|
-
function isKeyLiteral3(node, key) {
|
|
2870
|
-
return match(key).with({ type: AST_NODE_TYPES.Literal }, constTrue).with({ type: AST_NODE_TYPES.TemplateLiteral, expressions: [] }, constTrue).with({ type: AST_NODE_TYPES.Identifier }, () => !node.computed).otherwise(constFalse);
|
|
2871
|
-
}
|
|
2872
|
-
var no_unused_state_default = createRule({
|
|
2873
|
-
meta: {
|
|
2874
|
-
type: "problem",
|
|
2875
|
-
docs: {
|
|
2876
|
-
description: "Warns unused class component state.",
|
|
2877
|
-
[Symbol.for("rule_features")]: RULE_FEATURES48
|
|
2878
|
-
},
|
|
2879
|
-
messages: {
|
|
2880
|
-
noUnusedState: "Unused class component state in '{{className}}'"
|
|
2881
|
-
},
|
|
2882
|
-
schema: []
|
|
2883
|
-
},
|
|
2884
|
-
name: RULE_NAME48,
|
|
2885
|
-
create: create48,
|
|
2886
|
-
defaultOptions: []
|
|
2887
|
-
});
|
|
2888
|
-
function create48(context) {
|
|
2889
|
-
const classEntries = [];
|
|
2890
|
-
const methodEntries = [];
|
|
2891
|
-
const constructorEntries = [];
|
|
2892
|
-
const stateDefs = /* @__PURE__ */ new WeakMap();
|
|
2893
|
-
function classEnter(node) {
|
|
2894
|
-
classEntries.push(node);
|
|
2895
|
-
}
|
|
2896
|
-
function classExit() {
|
|
2897
|
-
const currentClass = classEntries.pop();
|
|
2898
|
-
if (currentClass == null || !ER25.isClassComponent(currentClass)) {
|
|
2899
|
-
return;
|
|
2900
|
-
}
|
|
2901
|
-
const className = AST8.getClassId(currentClass)?.name;
|
|
2902
|
-
const { node: defNode, isUsed = false } = stateDefs.get(currentClass) ?? {};
|
|
2903
|
-
if (defNode == null || isUsed) {
|
|
2904
|
-
return;
|
|
2905
|
-
}
|
|
2906
|
-
context.report({
|
|
2907
|
-
messageId: "noUnusedState",
|
|
2908
|
-
node: defNode,
|
|
2909
|
-
data: {
|
|
2910
|
-
className: className ?? "Component"
|
|
2911
|
-
}
|
|
2912
|
-
});
|
|
2913
|
-
}
|
|
2914
|
-
function methodEnter(node) {
|
|
2915
|
-
methodEntries.push(node);
|
|
2916
|
-
const currentClass = classEntries.at(-1);
|
|
2917
|
-
if (currentClass == null || !ER25.isClassComponent(currentClass)) {
|
|
2918
|
-
return;
|
|
2919
|
-
}
|
|
2920
|
-
if (node.static) {
|
|
2921
|
-
if (ER25.isGetDerivedStateFromProps(node) && isMatching({ params: [P.nonNullable, ...P.array()] })(node.value)) {
|
|
2922
|
-
const defNode = stateDefs.get(currentClass)?.node;
|
|
2923
|
-
stateDefs.set(currentClass, { node: defNode, isUsed: true });
|
|
2924
|
-
}
|
|
2925
|
-
return;
|
|
2926
|
-
}
|
|
2927
|
-
if (AST8.getPropertyName(node.key) === "state") {
|
|
2928
|
-
stateDefs.set(currentClass, { node: node.key, isUsed: false });
|
|
2929
|
-
}
|
|
2930
|
-
}
|
|
2931
|
-
function methodExit() {
|
|
2932
|
-
methodEntries.pop();
|
|
2933
|
-
}
|
|
2934
|
-
function constructorEnter(node) {
|
|
2935
|
-
constructorEntries.push(node);
|
|
2936
|
-
}
|
|
2937
|
-
function constructorExit() {
|
|
2938
|
-
constructorEntries.pop();
|
|
2939
|
-
}
|
|
2940
|
-
return {
|
|
2941
|
-
AssignmentExpression(node) {
|
|
2942
|
-
if (!ER25.isAssignmentToThisState(node)) {
|
|
2943
|
-
return;
|
|
2944
|
-
}
|
|
2945
|
-
const currentClass = classEntries.at(-1);
|
|
2946
|
-
if (currentClass == null || !ER25.isClassComponent(currentClass)) {
|
|
2947
|
-
return;
|
|
2948
|
-
}
|
|
2949
|
-
const currentConstructor = constructorEntries.at(-1);
|
|
2950
|
-
if (currentConstructor == null || !currentClass.body.body.includes(currentConstructor)) {
|
|
2951
|
-
return;
|
|
2952
|
-
}
|
|
2953
|
-
const isUsed = stateDefs.get(currentClass)?.isUsed ?? false;
|
|
2954
|
-
stateDefs.set(currentClass, { node: node.left, isUsed });
|
|
2955
|
-
},
|
|
2956
|
-
ClassDeclaration: classEnter,
|
|
2957
|
-
"ClassDeclaration:exit": classExit,
|
|
2958
|
-
ClassExpression: classEnter,
|
|
2959
|
-
"ClassExpression:exit": classExit,
|
|
2960
|
-
MemberExpression(node) {
|
|
2961
|
-
if (!AST8.isThisExpression(node.object)) {
|
|
2962
|
-
return;
|
|
2963
|
-
}
|
|
2964
|
-
if (AST8.getPropertyName(node.property) !== "state") {
|
|
2965
|
-
return;
|
|
2966
|
-
}
|
|
2967
|
-
const currentClass = classEntries.at(-1);
|
|
2968
|
-
if (currentClass == null || !ER25.isClassComponent(currentClass)) {
|
|
2969
|
-
return;
|
|
2970
|
-
}
|
|
2971
|
-
const currentMethod = methodEntries.at(-1);
|
|
2972
|
-
if (currentMethod == null || currentMethod.static) {
|
|
2973
|
-
return;
|
|
2974
|
-
}
|
|
2975
|
-
if (currentMethod === constructorEntries.at(-1)) {
|
|
2976
|
-
return;
|
|
2977
|
-
}
|
|
2978
|
-
if (!currentClass.body.body.includes(currentMethod)) {
|
|
2979
|
-
return;
|
|
2980
|
-
}
|
|
2981
|
-
const defNode = stateDefs.get(currentClass)?.node;
|
|
2982
|
-
stateDefs.set(currentClass, { node: defNode, isUsed: true });
|
|
2983
|
-
},
|
|
2984
|
-
MethodDefinition: methodEnter,
|
|
2985
|
-
"MethodDefinition:exit": methodExit,
|
|
2986
|
-
"MethodDefinition[key.name='constructor']": constructorEnter,
|
|
2987
|
-
"MethodDefinition[key.name='constructor']:exit": constructorExit,
|
|
2988
|
-
PropertyDefinition: methodEnter,
|
|
2989
|
-
"PropertyDefinition:exit": methodExit,
|
|
2990
|
-
VariableDeclarator(node) {
|
|
2991
|
-
const currentClass = classEntries.at(-1);
|
|
2992
|
-
if (currentClass == null || !ER25.isClassComponent(currentClass)) {
|
|
2993
|
-
return;
|
|
2994
|
-
}
|
|
2995
|
-
const currentMethod = methodEntries.at(-1);
|
|
2996
|
-
if (currentMethod == null || currentMethod.static) {
|
|
2997
|
-
return;
|
|
2998
|
-
}
|
|
2999
|
-
if (currentMethod === constructorEntries.at(-1)) {
|
|
3000
|
-
return;
|
|
3001
|
-
}
|
|
3002
|
-
if (!currentClass.body.body.includes(currentMethod)) {
|
|
3003
|
-
return;
|
|
3004
|
-
}
|
|
3005
|
-
if (node.init == null || !AST8.isThisExpression(node.init) || node.id.type !== AST_NODE_TYPES.ObjectPattern) {
|
|
3006
|
-
return;
|
|
3007
|
-
}
|
|
3008
|
-
const hasState = node.id.properties.some((prop) => {
|
|
3009
|
-
if (prop.type === AST_NODE_TYPES.Property && isKeyLiteral3(prop, prop.key)) {
|
|
3010
|
-
return AST8.getPropertyName(prop.key) === "state";
|
|
3011
|
-
}
|
|
3012
|
-
return false;
|
|
3013
|
-
});
|
|
3014
|
-
if (!hasState) {
|
|
3015
|
-
return;
|
|
3016
|
-
}
|
|
3017
|
-
const defNode = stateDefs.get(currentClass)?.node;
|
|
3018
|
-
stateDefs.set(currentClass, { node: defNode, isUsed: true });
|
|
3019
|
-
}
|
|
3020
|
-
};
|
|
3021
|
-
}
|
|
3022
|
-
var RULE_NAME49 = "no-use-context";
|
|
3023
|
-
var RULE_FEATURES49 = [
|
|
3024
|
-
"MOD"
|
|
3025
|
-
];
|
|
3026
|
-
var no_use_context_default = createRule({
|
|
3027
|
-
meta: {
|
|
3028
|
-
type: "problem",
|
|
3029
|
-
docs: {
|
|
3030
|
-
description: "Replaces usages of `useContext` with `use`.",
|
|
3031
|
-
[Symbol.for("rule_features")]: RULE_FEATURES49
|
|
3032
|
-
},
|
|
3033
|
-
fixable: "code",
|
|
3034
|
-
messages: {
|
|
3035
|
-
noUseContext: "In React 19, 'use' is preferred over 'useContext' because it is more flexible."
|
|
3036
|
-
},
|
|
3037
|
-
schema: []
|
|
3038
|
-
},
|
|
3039
|
-
name: RULE_NAME49,
|
|
3040
|
-
create: create49,
|
|
3041
|
-
defaultOptions: []
|
|
3042
|
-
});
|
|
3043
|
-
function create49(context) {
|
|
3044
|
-
if (!context.sourceCode.text.includes("useContext")) return {};
|
|
3045
|
-
const settings4 = getSettingsFromContext(context);
|
|
3046
|
-
if (compare(settings4.version, "19.0.0", "<")) {
|
|
3047
|
-
return {};
|
|
3048
|
-
}
|
|
3049
|
-
const useContextNames = /* @__PURE__ */ new Set();
|
|
3050
|
-
const hookCalls = /* @__PURE__ */ new Set();
|
|
3051
|
-
return {
|
|
3052
|
-
CallExpression(node) {
|
|
3053
|
-
if (!ER25.isReactHookCall(node)) {
|
|
3054
|
-
return;
|
|
3055
|
-
}
|
|
3056
|
-
hookCalls.add(node);
|
|
3057
|
-
},
|
|
3058
|
-
ImportDeclaration(node) {
|
|
3059
|
-
if (node.source.value !== settings4.importSource) {
|
|
3060
|
-
return;
|
|
3061
|
-
}
|
|
3062
|
-
const isUseImported = node.specifiers.some(isMatching({ local: { type: AST_NODE_TYPES.Identifier, name: "use" } }));
|
|
3063
|
-
for (const specifier of node.specifiers) {
|
|
3064
|
-
if (specifier.type !== AST_NODE_TYPES.ImportSpecifier) continue;
|
|
3065
|
-
if (specifier.imported.type !== AST_NODE_TYPES.Identifier) continue;
|
|
3066
|
-
if (specifier.imported.name === "useContext") {
|
|
3067
|
-
if (specifier.local.name !== "useContext") {
|
|
3068
|
-
useContextNames.add(specifier.local.name);
|
|
3069
|
-
}
|
|
3070
|
-
context.report({
|
|
3071
|
-
messageId: "noUseContext",
|
|
3072
|
-
node: specifier,
|
|
3073
|
-
fix(fixer) {
|
|
3074
|
-
if (isUseImported) {
|
|
3075
|
-
const tokenBefore = context.sourceCode.getTokenBefore(specifier);
|
|
3076
|
-
return [
|
|
3077
|
-
fixer.remove(specifier),
|
|
3078
|
-
...tokenBefore?.value === "," ? [fixer.replaceTextRange([tokenBefore.range[1], specifier.range[0]], "")] : [],
|
|
3079
|
-
...getCorrelativeTokens(
|
|
3080
|
-
context,
|
|
3081
|
-
specifier
|
|
3082
|
-
).map((token) => fixer.remove(token))
|
|
3083
|
-
];
|
|
3084
|
-
}
|
|
3085
|
-
return fixer.replaceText(specifier.imported, "use");
|
|
3086
|
-
}
|
|
3087
|
-
});
|
|
3088
|
-
}
|
|
3089
|
-
}
|
|
3090
|
-
},
|
|
3091
|
-
"Program:exit"() {
|
|
3092
|
-
const isUseContextCall = ER25.isReactHookCallWithNameAlias(context, "useContext", [...useContextNames]);
|
|
3093
|
-
for (const node of hookCalls) {
|
|
3094
|
-
if (!isUseContextCall(node)) {
|
|
3095
|
-
continue;
|
|
3096
|
-
}
|
|
3097
|
-
context.report({
|
|
3098
|
-
messageId: "noUseContext",
|
|
3099
|
-
node: node.callee,
|
|
3100
|
-
fix(fixer) {
|
|
3101
|
-
switch (node.callee.type) {
|
|
3102
|
-
case AST_NODE_TYPES.Identifier:
|
|
3103
|
-
return fixer.replaceText(node.callee, "use");
|
|
3104
|
-
case AST_NODE_TYPES.MemberExpression:
|
|
3105
|
-
return fixer.replaceText(node.callee.property, "use");
|
|
3106
|
-
}
|
|
3107
|
-
return null;
|
|
3108
|
-
}
|
|
3109
|
-
});
|
|
3110
|
-
}
|
|
3111
|
-
}
|
|
3112
|
-
};
|
|
3113
|
-
}
|
|
3114
|
-
function getCorrelativeTokens(context, node) {
|
|
3115
|
-
const tokenBefore = context.sourceCode.getTokenBefore(node);
|
|
3116
|
-
const tokenAfter = context.sourceCode.getTokenAfter(node);
|
|
3117
|
-
const tokens = [];
|
|
3118
|
-
if (tokenAfter?.value !== "," && tokenBefore?.value === ",") {
|
|
3119
|
-
tokens.push(tokenBefore);
|
|
3120
|
-
}
|
|
3121
|
-
if (tokenAfter?.value === ",") {
|
|
3122
|
-
tokens.push(tokenAfter);
|
|
3123
|
-
}
|
|
3124
|
-
return tokens;
|
|
3125
|
-
}
|
|
3126
|
-
var RULE_NAME50 = "no-useless-forward-ref";
|
|
3127
|
-
var RULE_FEATURES50 = [];
|
|
3128
|
-
var no_useless_forward_ref_default = createRule({
|
|
3129
|
-
meta: {
|
|
3130
|
-
type: "problem",
|
|
3131
|
-
docs: {
|
|
3132
|
-
description: "Disallow useless `forwardRef` calls on components that don't use `ref`s.",
|
|
3133
|
-
[Symbol.for("rule_features")]: RULE_FEATURES50
|
|
3134
|
-
},
|
|
3135
|
-
messages: {
|
|
3136
|
-
noUselessForwardRef: "A 'forwardRef' is used with this component but no 'ref' parameter is set."
|
|
3137
|
-
},
|
|
3138
|
-
schema: []
|
|
3139
|
-
},
|
|
3140
|
-
name: RULE_NAME50,
|
|
3141
|
-
create: create50,
|
|
3142
|
-
defaultOptions: []
|
|
3143
|
-
});
|
|
3144
|
-
function create50(context) {
|
|
3145
|
-
return {
|
|
3146
|
-
CallExpression(node) {
|
|
3147
|
-
if (!ER25.isForwardRefCall(context, node)) {
|
|
3148
|
-
return;
|
|
3149
|
-
}
|
|
3150
|
-
const [component] = node.arguments;
|
|
3151
|
-
if (component == null || !AST8.isFunction(component)) {
|
|
3152
|
-
return;
|
|
3153
|
-
}
|
|
3154
|
-
const ref = component.params[1];
|
|
3155
|
-
if (ref != null) {
|
|
3156
|
-
return;
|
|
3157
|
-
}
|
|
3158
|
-
context.report({
|
|
3159
|
-
messageId: "noUselessForwardRef",
|
|
3160
|
-
node: node.callee
|
|
3161
|
-
});
|
|
3162
|
-
}
|
|
3163
|
-
};
|
|
3164
|
-
}
|
|
3165
|
-
var RULE_NAME51 = "no-useless-fragment";
|
|
3166
|
-
var defaultOptions = [{
|
|
3167
|
-
allowExpressions: true
|
|
3168
|
-
}];
|
|
3169
|
-
var no_useless_fragment_default = createRule({
|
|
3170
|
-
meta: {
|
|
3171
|
-
type: "problem",
|
|
3172
|
-
defaultOptions: [...defaultOptions],
|
|
3173
|
-
docs: {
|
|
3174
|
-
description: "Disallow useless fragment elements."
|
|
3175
|
-
},
|
|
3176
|
-
fixable: "code",
|
|
3177
|
-
messages: {
|
|
3178
|
-
uselessFragment: "A fragment {{reason}} is useless."
|
|
3179
|
-
},
|
|
3180
|
-
schema: [{
|
|
3181
|
-
type: "object",
|
|
3182
|
-
additionalProperties: false,
|
|
3183
|
-
properties: {
|
|
3184
|
-
allowExpressions: {
|
|
3185
|
-
type: "boolean",
|
|
3186
|
-
description: "Allow fragments with a single expression child"
|
|
3187
|
-
}
|
|
3188
|
-
}
|
|
3189
|
-
}]
|
|
3190
|
-
},
|
|
3191
|
-
name: RULE_NAME51,
|
|
3192
|
-
create: create51,
|
|
3193
|
-
defaultOptions
|
|
3194
|
-
});
|
|
3195
|
-
function create51(context, [option]) {
|
|
3196
|
-
const { allowExpressions = true } = option;
|
|
3197
|
-
return {
|
|
3198
|
-
JSXElement(node) {
|
|
3199
|
-
if (!ER25.isFragmentElement(context, node)) return;
|
|
3200
|
-
checkNode(context, node, allowExpressions);
|
|
3201
|
-
},
|
|
3202
|
-
JSXFragment(node) {
|
|
3203
|
-
checkNode(context, node, allowExpressions);
|
|
3204
|
-
}
|
|
3205
|
-
};
|
|
3206
|
-
}
|
|
3207
|
-
function isWhiteSpace(node) {
|
|
3208
|
-
return typeof node.value === "string" && node.raw.trim() === "";
|
|
3209
|
-
}
|
|
3210
|
-
function isPaddingSpaces(node) {
|
|
3211
|
-
return ER25.isJsxText(node) && isWhiteSpace(node) && node.raw.includes("\n");
|
|
3212
|
-
}
|
|
3213
|
-
function trimLikeReact(text) {
|
|
3214
|
-
const leadingSpaces = /^\s*/.exec(text)?.[0] ?? "";
|
|
3215
|
-
const trailingSpaces = /\s*$/.exec(text)?.[0] ?? "";
|
|
3216
|
-
const start = leadingSpaces.includes("\n") ? leadingSpaces.length : 0;
|
|
3217
|
-
const end = trailingSpaces.includes("\n") ? text.length - trailingSpaces.length : text.length;
|
|
3218
|
-
return text.slice(start, end);
|
|
3219
|
-
}
|
|
3220
|
-
function checkNode(context, node, allowExpressions) {
|
|
3221
|
-
const initialScope = context.sourceCode.getScope(node);
|
|
3222
|
-
if (ER25.isKeyedElement(context, node, initialScope)) {
|
|
3223
|
-
return;
|
|
3224
|
-
}
|
|
3225
|
-
if (ER25.isHostElement(context, node.parent)) {
|
|
3226
|
-
context.report({
|
|
3227
|
-
messageId: "uselessFragment",
|
|
3228
|
-
node,
|
|
3229
|
-
data: {
|
|
3230
|
-
reason: "placed inside a host component"
|
|
3231
|
-
},
|
|
3232
|
-
fix: getFix2(context, node)
|
|
3233
|
-
});
|
|
3234
|
-
}
|
|
3235
|
-
if (node.children.length === 0) {
|
|
3236
|
-
context.report({
|
|
3237
|
-
messageId: "uselessFragment",
|
|
3238
|
-
node,
|
|
3239
|
-
data: {
|
|
3240
|
-
reason: "contains less than two children"
|
|
3241
|
-
},
|
|
3242
|
-
fix: getFix2(context, node)
|
|
3243
|
-
});
|
|
3244
|
-
return;
|
|
3245
|
-
}
|
|
3246
|
-
const isChildElement = AST8.isOneOf([AST_NODE_TYPES.JSXElement, AST_NODE_TYPES.JSXFragment])(node.parent);
|
|
3247
|
-
switch (true) {
|
|
3248
|
-
// <Foo content={<>ee eeee eeee ...</>} />
|
|
3249
|
-
case (allowExpressions && !isChildElement && node.children.length === 1 && ER25.isJsxText(node.children.at(0))): {
|
|
3250
|
-
return;
|
|
3251
|
-
}
|
|
3252
|
-
// <Foo><>hello, world</></Foo>
|
|
3253
|
-
case (!allowExpressions && isChildElement): {
|
|
3254
|
-
context.report({
|
|
3255
|
-
messageId: "uselessFragment",
|
|
3256
|
-
node,
|
|
3257
|
-
data: {
|
|
3258
|
-
reason: "contains less than two children"
|
|
3259
|
-
},
|
|
3260
|
-
fix: getFix2(context, node)
|
|
3261
|
-
});
|
|
3262
|
-
return;
|
|
3263
|
-
}
|
|
3264
|
-
case (!allowExpressions && !isChildElement && node.children.length === 1): {
|
|
3265
|
-
context.report({
|
|
3266
|
-
messageId: "uselessFragment",
|
|
3267
|
-
node,
|
|
3268
|
-
data: {
|
|
3269
|
-
reason: "contains less than two children"
|
|
3270
|
-
},
|
|
3271
|
-
fix: getFix2(context, node)
|
|
3272
|
-
});
|
|
3273
|
-
return;
|
|
3274
|
-
}
|
|
3275
|
-
}
|
|
3276
|
-
const nonPaddingChildren = node.children.filter((child) => !isPaddingSpaces(child));
|
|
3277
|
-
const firstNonPaddingChild = nonPaddingChildren.at(0);
|
|
3278
|
-
switch (true) {
|
|
3279
|
-
case nonPaddingChildren.length === 0:
|
|
3280
|
-
case (nonPaddingChildren.length === 1 && firstNonPaddingChild?.type !== AST_NODE_TYPES.JSXExpressionContainer): {
|
|
3281
|
-
context.report({
|
|
3282
|
-
messageId: "uselessFragment",
|
|
3283
|
-
node,
|
|
3284
|
-
data: {
|
|
3285
|
-
reason: "contains less than two children"
|
|
3286
|
-
},
|
|
3287
|
-
fix: getFix2(context, node)
|
|
3288
|
-
});
|
|
3289
|
-
return;
|
|
3290
|
-
}
|
|
3291
|
-
}
|
|
3292
|
-
return;
|
|
3293
|
-
}
|
|
3294
|
-
function getFix2(context, node) {
|
|
3295
|
-
if (!canFix(context, node)) return null;
|
|
3296
|
-
return (fixer) => {
|
|
3297
|
-
const opener = node.type === AST_NODE_TYPES.JSXFragment ? node.openingFragment : node.openingElement;
|
|
3298
|
-
const closer = node.type === AST_NODE_TYPES.JSXFragment ? node.closingFragment : node.closingElement;
|
|
3299
|
-
const childrenText = opener.type === AST_NODE_TYPES.JSXOpeningElement && opener.selfClosing ? "" : context.sourceCode.getText().slice(opener.range[1], closer?.range[0]);
|
|
3300
|
-
return fixer.replaceText(node, trimLikeReact(childrenText));
|
|
3301
|
-
};
|
|
3302
|
-
}
|
|
3303
|
-
function canFix(context, node) {
|
|
3304
|
-
if (node.parent.type === AST_NODE_TYPES.JSXElement || node.parent.type === AST_NODE_TYPES.JSXFragment) {
|
|
3305
|
-
return ER25.isHostElement(context, node.parent);
|
|
3306
|
-
}
|
|
3307
|
-
if (node.children.length === 0) {
|
|
3308
|
-
return false;
|
|
3309
|
-
}
|
|
3310
|
-
if (node.children.some((child) => ER25.isJsxText(child) && !isWhiteSpace(child) || AST8.is(AST_NODE_TYPES.JSXExpressionContainer)(child))) {
|
|
3311
|
-
return false;
|
|
3312
|
-
}
|
|
3313
|
-
return true;
|
|
3314
|
-
}
|
|
3315
|
-
var RULE_NAME52 = "prefer-destructuring-assignment";
|
|
3316
|
-
var RULE_FEATURES51 = [];
|
|
3317
|
-
function isMemberExpressionWithObjectName(node) {
|
|
3318
|
-
return node.object.type === AST_NODE_TYPES.Identifier && "name" in node.object;
|
|
3319
|
-
}
|
|
3320
|
-
var prefer_destructuring_assignment_default = createRule({
|
|
3321
|
-
meta: {
|
|
3322
|
-
type: "problem",
|
|
3323
|
-
docs: {
|
|
3324
|
-
description: "Enforces destructuring assignment for component props and context.",
|
|
3325
|
-
[Symbol.for("rule_features")]: RULE_FEATURES51
|
|
3326
|
-
},
|
|
3327
|
-
messages: {
|
|
3328
|
-
preferDestructuringAssignment: "Use destructuring assignment for {{name}}."
|
|
3329
|
-
},
|
|
3330
|
-
schema: []
|
|
3331
|
-
},
|
|
3332
|
-
name: RULE_NAME52,
|
|
3333
|
-
create: create52,
|
|
3334
|
-
defaultOptions: []
|
|
3335
|
-
});
|
|
3336
|
-
function create52(context) {
|
|
3337
|
-
const { ctx, listeners } = ER25.useComponentCollector(context);
|
|
3338
|
-
const memberExpressionWithNames = [];
|
|
3339
|
-
return {
|
|
3340
|
-
...listeners,
|
|
3341
|
-
MemberExpression(node) {
|
|
3342
|
-
if (isMemberExpressionWithObjectName(node)) {
|
|
3343
|
-
const scope = context.sourceCode.getScope(node);
|
|
3344
|
-
memberExpressionWithNames.push([scope, node]);
|
|
3345
|
-
}
|
|
3346
|
-
},
|
|
3347
|
-
"Program:exit"(program) {
|
|
3348
|
-
const components = [
|
|
3349
|
-
...ctx.getAllComponents(program).values()
|
|
3350
|
-
];
|
|
3351
|
-
function isFunctionComponent(block) {
|
|
3352
|
-
if (!AST8.isFunction(block)) {
|
|
3353
|
-
return false;
|
|
3354
|
-
}
|
|
3355
|
-
const id = AST8.getFunctionId(block);
|
|
3356
|
-
return id != null && ER25.isComponentNameLoose(id.name) && components.some((component) => component.node === block);
|
|
3357
|
-
}
|
|
3358
|
-
for (const [initialScope, memberExpression] of memberExpressionWithNames) {
|
|
3359
|
-
let scope = initialScope;
|
|
3360
|
-
let isComponent = isFunctionComponent(scope.block);
|
|
3361
|
-
while (!isComponent && scope.upper != null && scope.upper !== scope) {
|
|
3362
|
-
scope = scope.upper;
|
|
3363
|
-
isComponent = isFunctionComponent(scope.block);
|
|
3364
|
-
}
|
|
3365
|
-
if (!isComponent) {
|
|
3366
|
-
continue;
|
|
3367
|
-
}
|
|
3368
|
-
const component = scope.block;
|
|
3369
|
-
if (!("params" in component)) {
|
|
3370
|
-
continue;
|
|
3371
|
-
}
|
|
3372
|
-
const [props, ctx2] = component.params;
|
|
3373
|
-
const isMatch = (node) => node != null && node.type === AST_NODE_TYPES.Identifier && node.name === memberExpression.object.name;
|
|
3374
|
-
if (isMatch(props)) {
|
|
3375
|
-
context.report({
|
|
3376
|
-
messageId: "preferDestructuringAssignment",
|
|
3377
|
-
node: memberExpression,
|
|
3378
|
-
data: {
|
|
3379
|
-
name: "props"
|
|
3380
|
-
}
|
|
3381
|
-
});
|
|
3382
|
-
}
|
|
3383
|
-
if (isMatch(ctx2)) {
|
|
3384
|
-
context.report({
|
|
3385
|
-
messageId: "preferDestructuringAssignment",
|
|
3386
|
-
node: memberExpression,
|
|
3387
|
-
data: {
|
|
3388
|
-
name: "context"
|
|
3389
|
-
}
|
|
3390
|
-
});
|
|
3391
|
-
}
|
|
3392
|
-
}
|
|
3393
|
-
}
|
|
3394
|
-
};
|
|
3395
|
-
}
|
|
3396
|
-
var RULE_NAME53 = "prefer-react-namespace-import";
|
|
3397
|
-
var RULE_FEATURES52 = [
|
|
3398
|
-
"FIX"
|
|
3399
|
-
];
|
|
3400
|
-
var prefer_react_namespace_import_default = createRule({
|
|
3401
|
-
meta: {
|
|
3402
|
-
type: "problem",
|
|
3403
|
-
docs: {
|
|
3404
|
-
description: "Enforces React is imported via a namespace import.",
|
|
3405
|
-
[Symbol.for("rule_features")]: RULE_FEATURES52
|
|
3406
|
-
},
|
|
3407
|
-
fixable: "code",
|
|
3408
|
-
messages: {
|
|
3409
|
-
preferReactNamespaceImport: `Prefer importing React as 'import * as React from "{{importSource}}"';`
|
|
3410
|
-
},
|
|
3411
|
-
schema: []
|
|
3412
|
-
},
|
|
3413
|
-
name: RULE_NAME53,
|
|
3414
|
-
create: create53,
|
|
3415
|
-
defaultOptions: []
|
|
3416
|
-
});
|
|
3417
|
-
function create53(context) {
|
|
3418
|
-
const { importSource } = getSettingsFromContext(context);
|
|
3419
|
-
return {
|
|
3420
|
-
[`ImportDeclaration[source.value="${importSource}"] ImportDefaultSpecifier`](node) {
|
|
3421
|
-
const hasOtherSpecifiers = node.parent.specifiers.length > 1;
|
|
3422
|
-
context.report({
|
|
3423
|
-
messageId: "preferReactNamespaceImport",
|
|
3424
|
-
node: hasOtherSpecifiers ? node : node.parent,
|
|
3425
|
-
data: { importSource },
|
|
3426
|
-
fix(fixer) {
|
|
3427
|
-
const importDeclarationText = context.sourceCode.getText(node.parent);
|
|
3428
|
-
const semi = importDeclarationText.endsWith(";") ? ";" : "";
|
|
3429
|
-
const quote = node.parent.source.raw.at(0) ?? "'";
|
|
3430
|
-
const isTypeImport = node.parent.importKind === "type";
|
|
3431
|
-
const importStringPrefix = `import${isTypeImport ? " type" : ""}`;
|
|
3432
|
-
const importSourceQuoted = `${quote}${importSource}${quote}`;
|
|
3433
|
-
if (!hasOtherSpecifiers) {
|
|
3434
|
-
return fixer.replaceText(
|
|
3435
|
-
node.parent,
|
|
3436
|
-
`${importStringPrefix} * as ${node.local.name} from ${importSourceQuoted}${semi}`
|
|
3437
|
-
);
|
|
3438
|
-
}
|
|
3439
|
-
const specifiers = importDeclarationText.slice(importDeclarationText.indexOf("{"), importDeclarationText.indexOf("}") + 1);
|
|
3440
|
-
return fixer.replaceText(
|
|
3441
|
-
node.parent,
|
|
3442
|
-
[
|
|
3443
|
-
`${importStringPrefix} * as ${node.local.name} from ${importSourceQuoted}${semi}`,
|
|
3444
|
-
`${importStringPrefix} ${specifiers} from ${importSourceQuoted}${semi}`
|
|
3445
|
-
].join("\n")
|
|
3446
|
-
);
|
|
3447
|
-
}
|
|
3448
|
-
});
|
|
3449
|
-
}
|
|
3450
|
-
};
|
|
3451
|
-
}
|
|
3452
|
-
var RULE_NAME54 = "prefer-read-only-props";
|
|
3453
|
-
var RULE_FEATURES53 = [
|
|
3454
|
-
"TSC",
|
|
3455
|
-
"EXP"
|
|
3456
|
-
];
|
|
3457
|
-
var prefer_read_only_props_default = createRule({
|
|
3458
|
-
meta: {
|
|
3459
|
-
type: "problem",
|
|
3460
|
-
docs: {
|
|
3461
|
-
description: "Enforces read-only props in components.",
|
|
3462
|
-
[Symbol.for("rule_features")]: RULE_FEATURES53
|
|
3463
|
-
},
|
|
3464
|
-
messages: {
|
|
3465
|
-
preferReadOnlyProps: "A function component's props should be read-only."
|
|
3466
|
-
},
|
|
3467
|
-
schema: []
|
|
3468
|
-
},
|
|
3469
|
-
name: RULE_NAME54,
|
|
3470
|
-
create: create54,
|
|
3471
|
-
defaultOptions: []
|
|
3472
|
-
});
|
|
3473
|
-
function create54(context) {
|
|
3474
|
-
const services = ESLintUtils.getParserServices(context, false);
|
|
3475
|
-
const { ctx, listeners } = ER25.useComponentCollector(context);
|
|
3476
|
-
return {
|
|
3477
|
-
...listeners,
|
|
3478
|
-
"Program:exit"(program) {
|
|
3479
|
-
const components = ctx.getAllComponents(program);
|
|
3480
|
-
for (const [, component] of components) {
|
|
3481
|
-
const [props] = component.node.params;
|
|
3482
|
-
if (props == null) {
|
|
3483
|
-
continue;
|
|
3484
|
-
}
|
|
3485
|
-
const propsType = getConstrainedTypeAtLocation(services, props);
|
|
3486
|
-
if (isTypeReadonlyLoose(services, propsType)) {
|
|
3487
|
-
continue;
|
|
3488
|
-
}
|
|
3489
|
-
context.report({ messageId: "preferReadOnlyProps", node: props });
|
|
3490
|
-
}
|
|
3491
|
-
}
|
|
3492
|
-
};
|
|
3493
|
-
}
|
|
3494
|
-
function isTypeReadonlyLoose(services, type) {
|
|
3495
|
-
if (isTypeReadonly(services.program, type)) return true;
|
|
3496
|
-
try {
|
|
3497
|
-
const im = getTypeImmutability(services.program, type);
|
|
3498
|
-
return isUnknown(im) || isImmutable(im) || isReadonlyShallow(im) || isReadonlyDeep(im);
|
|
3499
|
-
} catch {
|
|
3500
|
-
return true;
|
|
3501
|
-
}
|
|
3502
|
-
}
|
|
3503
|
-
var RULE_NAME55 = "prefer-shorthand-boolean";
|
|
3504
|
-
var RULE_FEATURES54 = [
|
|
3505
|
-
"FIX"
|
|
3506
|
-
];
|
|
3507
|
-
var prefer_shorthand_boolean_default = createRule({
|
|
3508
|
-
meta: {
|
|
3509
|
-
type: "problem",
|
|
3510
|
-
docs: {
|
|
3511
|
-
description: "Enforces shorthand syntax for boolean attributes.",
|
|
3512
|
-
[Symbol.for("rule_features")]: RULE_FEATURES54
|
|
3513
|
-
},
|
|
3514
|
-
fixable: "code",
|
|
3515
|
-
messages: {
|
|
3516
|
-
preferShorthandBoolean: "Use shorthand boolean attribute '{{propName}}'."
|
|
3517
|
-
},
|
|
3518
|
-
schema: []
|
|
3519
|
-
},
|
|
3520
|
-
name: RULE_NAME55,
|
|
3521
|
-
create: create55,
|
|
3522
|
-
defaultOptions: []
|
|
3523
|
-
});
|
|
3524
|
-
function create55(context) {
|
|
3525
|
-
return {
|
|
3526
|
-
JSXAttribute(node) {
|
|
3527
|
-
const { value } = node;
|
|
3528
|
-
const propName = ER25.getAttributeName(context, node);
|
|
3529
|
-
const hasValueTrue = value?.type === AST_NODE_TYPES.JSXExpressionContainer && value.expression.type === AST_NODE_TYPES.Literal && value.expression.value === true;
|
|
3530
|
-
if (!hasValueTrue) {
|
|
3531
|
-
return;
|
|
3532
|
-
}
|
|
3533
|
-
context.report({
|
|
3534
|
-
messageId: "preferShorthandBoolean",
|
|
3535
|
-
node: node.value ?? node,
|
|
3536
|
-
data: {
|
|
3537
|
-
propName
|
|
3538
|
-
},
|
|
3539
|
-
fix: (fixer) => fixer.removeRange([node.name.range[1], value.range[1]])
|
|
3540
|
-
});
|
|
3541
|
-
}
|
|
3542
|
-
};
|
|
3543
|
-
}
|
|
3544
|
-
var RULE_NAME56 = "prefer-shorthand-fragment";
|
|
3545
|
-
var RULE_FEATURES55 = [
|
|
3546
|
-
"FIX"
|
|
3547
|
-
];
|
|
3548
|
-
var prefer_shorthand_fragment_default = createRule({
|
|
3549
|
-
meta: {
|
|
3550
|
-
type: "problem",
|
|
3551
|
-
docs: {
|
|
3552
|
-
description: "Enforces shorthand syntax for fragments.",
|
|
3553
|
-
[Symbol.for("rule_features")]: RULE_FEATURES55
|
|
3554
|
-
},
|
|
3555
|
-
fixable: "code",
|
|
3556
|
-
messages: {
|
|
3557
|
-
preferShorthandFragment: "Use fragment shorthand syntax instead of 'Fragment' component."
|
|
3558
|
-
},
|
|
3559
|
-
schema: []
|
|
3560
|
-
},
|
|
3561
|
-
name: RULE_NAME56,
|
|
3562
|
-
create: create56,
|
|
3563
|
-
defaultOptions: []
|
|
3564
|
-
});
|
|
3565
|
-
function create56(context) {
|
|
3566
|
-
return {
|
|
3567
|
-
JSXElement(node) {
|
|
3568
|
-
if (!ER25.isFragmentElement(context, node)) return;
|
|
3569
|
-
const hasAttributes = node.openingElement.attributes.length > 0;
|
|
3570
|
-
if (hasAttributes) {
|
|
3571
|
-
return;
|
|
3572
|
-
}
|
|
3573
|
-
context.report({
|
|
3574
|
-
messageId: "preferShorthandFragment",
|
|
3575
|
-
node,
|
|
3576
|
-
fix: (fixer) => {
|
|
3577
|
-
const { closingElement, openingElement } = node;
|
|
3578
|
-
if (closingElement == null) {
|
|
3579
|
-
return [];
|
|
3580
|
-
}
|
|
3581
|
-
return [
|
|
3582
|
-
fixer.replaceTextRange([openingElement.range[0], openingElement.range[1]], "<>"),
|
|
3583
|
-
fixer.replaceTextRange([closingElement.range[0], closingElement.range[1]], "</>")
|
|
3584
|
-
];
|
|
3585
|
-
}
|
|
3586
|
-
});
|
|
3587
|
-
}
|
|
3588
|
-
};
|
|
3589
|
-
}
|
|
3590
|
-
|
|
3591
|
-
// src/plugin.ts
|
|
3592
|
-
var plugin = {
|
|
3593
|
-
meta: {
|
|
3594
|
-
name: name4,
|
|
3595
|
-
version
|
|
3596
|
-
},
|
|
3597
|
-
rules: {
|
|
3598
|
-
"avoid-shorthand-boolean": avoid_shorthand_boolean_default,
|
|
3599
|
-
"avoid-shorthand-fragment": avoid_shorthand_fragment_default,
|
|
3600
|
-
"no-access-state-in-setstate": no_access_state_in_setstate_default,
|
|
3601
|
-
"no-array-index-key": no_array_index_key_default,
|
|
3602
|
-
"no-children-count": no_children_count_default,
|
|
3603
|
-
"no-children-for-each": no_children_for_each_default,
|
|
3604
|
-
"no-children-map": no_children_map_default,
|
|
3605
|
-
"no-children-only": no_children_only_default,
|
|
3606
|
-
"no-children-prop": no_children_prop_default,
|
|
3607
|
-
"no-children-to-array": no_children_to_array_default,
|
|
3608
|
-
"no-class-component": no_class_component_default,
|
|
3609
|
-
"no-clone-element": no_clone_element_default,
|
|
3610
|
-
"no-comment-textnodes": no_comment_textnodes_default,
|
|
3611
|
-
"no-complex-conditional-rendering": no_complex_conditional_rendering_default,
|
|
3612
|
-
"no-component-will-mount": no_component_will_mount_default,
|
|
3613
|
-
"no-component-will-receive-props": no_component_will_receive_props_default,
|
|
3614
|
-
"no-component-will-update": no_component_will_update_default,
|
|
3615
|
-
"no-context-provider": no_context_provider_default,
|
|
3616
|
-
"no-create-ref": no_create_ref_default,
|
|
3617
|
-
"no-default-props": no_default_props_default,
|
|
3618
|
-
"no-direct-mutation-state": no_direct_mutation_state_default,
|
|
3619
|
-
"no-duplicate-key": no_duplicate_key_default,
|
|
3620
|
-
"no-forward-ref": no_forward_ref_default,
|
|
3621
|
-
"no-implicit-key": no_implicit_key_default,
|
|
3622
|
-
"no-leaked-conditional-rendering": no_leaked_conditional_rendering_default,
|
|
3623
|
-
"no-missing-component-display-name": no_missing_component_display_name_default,
|
|
3624
|
-
"no-missing-context-display-name": no_missing_context_display_name_default,
|
|
3625
|
-
"no-missing-key": no_missing_key_default,
|
|
3626
|
-
"no-misused-capture-owner-stack": no_misused_capture_owner_stack_default,
|
|
3627
|
-
"no-nested-component-definitions": no_nested_component_definitions_default,
|
|
3628
|
-
"no-nested-lazy-component-declarations": no_nested_lazy_component_declarations_default,
|
|
3629
|
-
"no-prop-types": no_prop_types_default,
|
|
3630
|
-
"no-redundant-should-component-update": no_redundant_should_component_update_default,
|
|
3631
|
-
"no-set-state-in-component-did-mount": no_set_state_in_component_did_mount_default,
|
|
3632
|
-
"no-set-state-in-component-did-update": no_set_state_in_component_did_update_default,
|
|
3633
|
-
"no-set-state-in-component-will-update": no_set_state_in_component_will_update_default,
|
|
3634
|
-
"no-string-refs": no_string_refs_default,
|
|
3635
|
-
"no-unsafe-component-will-mount": no_unsafe_component_will_mount_default,
|
|
3636
|
-
"no-unsafe-component-will-receive-props": no_unsafe_component_will_receive_props_default,
|
|
3637
|
-
"no-unsafe-component-will-update": no_unsafe_component_will_update_default,
|
|
3638
|
-
"no-unstable-context-value": no_unstable_context_value_default,
|
|
3639
|
-
"no-unstable-default-props": no_unstable_default_props_default,
|
|
3640
|
-
"no-unused-class-component-members": no_unused_class_component_members_default,
|
|
3641
|
-
"no-unused-state": no_unused_state_default,
|
|
3642
|
-
"no-use-context": no_use_context_default,
|
|
3643
|
-
"no-useless-forward-ref": no_useless_forward_ref_default,
|
|
3644
|
-
"no-useless-fragment": no_useless_fragment_default,
|
|
3645
|
-
"prefer-destructuring-assignment": prefer_destructuring_assignment_default,
|
|
3646
|
-
"prefer-react-namespace-import": prefer_react_namespace_import_default,
|
|
3647
|
-
"prefer-read-only-props": prefer_read_only_props_default,
|
|
3648
|
-
"prefer-shorthand-boolean": prefer_shorthand_boolean_default,
|
|
3649
|
-
"prefer-shorthand-fragment": prefer_shorthand_fragment_default,
|
|
3650
|
-
// Part: JSX only rules
|
|
3651
|
-
"jsx-no-duplicate-props": jsx_no_duplicate_props_default,
|
|
3652
|
-
"jsx-no-undef": jsx_no_undef_default,
|
|
3653
|
-
"jsx-uses-react": jsx_uses_react_default,
|
|
3654
|
-
"jsx-uses-vars": jsx_uses_vars_default,
|
|
3655
|
-
// Part: deprecated rules
|
|
3656
|
-
/** @deprecated Use `no-useless-forward-ref` instead */
|
|
3657
|
-
"ensure-forward-ref-using-ref": no_useless_forward_ref_default,
|
|
3658
|
-
/** @deprecated Use `no-complex-conditional-rendering` instead */
|
|
3659
|
-
"no-complicated-conditional-rendering": no_complex_conditional_rendering_default,
|
|
3660
|
-
/** @deprecated Use `jsx-no-duplicate-props` instead */
|
|
3661
|
-
"no-duplicate-jsx-props": jsx_no_duplicate_props_default,
|
|
3662
|
-
/** @deprecated Use `no-nested-component-definitions` instead */
|
|
3663
|
-
"no-nested-components": no_nested_component_definitions_default,
|
|
3664
|
-
/** @deprecated Use `jsx-uses-vars` instead */
|
|
3665
|
-
"use-jsx-vars": jsx_uses_vars_default
|
|
3666
|
-
}
|
|
3667
|
-
};
|
|
3668
|
-
|
|
3669
|
-
// src/index.ts
|
|
3670
|
-
function makeConfig(config) {
|
|
3671
|
-
return {
|
|
3672
|
-
...config,
|
|
3673
|
-
plugins: {
|
|
3674
|
-
"react-x": plugin
|
|
3675
|
-
}
|
|
3676
|
-
};
|
|
3677
|
-
}
|
|
3678
|
-
function makeLegacyConfig({ rules: rules4 }) {
|
|
3679
|
-
return {
|
|
3680
|
-
plugins: ["react-x"],
|
|
3681
|
-
rules: rules4
|
|
3682
|
-
};
|
|
3683
|
-
}
|
|
3684
|
-
var index_default = {
|
|
3685
|
-
...plugin,
|
|
3686
|
-
configs: {
|
|
3687
|
-
["recommended"]: makeConfig(recommended_exports),
|
|
3688
|
-
["recommended-legacy"]: makeLegacyConfig(recommended_exports),
|
|
3689
|
-
["recommended-type-checked"]: makeConfig(recommended_type_checked_exports),
|
|
3690
|
-
["recommended-type-checked-legacy"]: makeLegacyConfig(recommended_type_checked_exports),
|
|
3691
|
-
["recommended-typescript"]: makeConfig(recommended_typescript_exports),
|
|
3692
|
-
["recommended-typescript-legacy"]: makeLegacyConfig(recommended_typescript_exports)
|
|
3693
|
-
}
|
|
3694
|
-
};
|
|
3695
|
-
|
|
3696
|
-
export { index_default as default };
|