@agilebot/eslint-plugin 0.8.9 → 0.9.0
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/LICENSE +9 -9
- package/README.md +11 -11
- package/dist/index.js +137 -193
- package/package.json +6 -7
- package/dist/index.mjs +0 -2763
package/dist/index.js
CHANGED
|
@@ -1,41 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
*
|
|
8
|
-
*/
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { AST_NODE_TYPES, ESLintUtils } from "@typescript-eslint/utils";
|
|
3
|
+
import * as fs from "node:fs";
|
|
4
|
+
import * as path$1 from "node:path";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { isCamelCase, isPascalCase, tsImport } from "@agilebot/eslint-utils";
|
|
7
|
+
import * as Components from "eslint-plugin-react/lib/util/Components.js";
|
|
9
8
|
|
|
10
9
|
//#region rolldown:runtime
|
|
11
|
-
var
|
|
12
|
-
var __defProp = Object.defineProperty;
|
|
13
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
14
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
15
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
16
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
17
|
-
var __copyProps = (to, from, except, desc) => {
|
|
18
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
19
|
-
key = keys[i];
|
|
20
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
21
|
-
get: ((k) => from[k]).bind(null, key),
|
|
22
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
return to;
|
|
26
|
-
};
|
|
27
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
28
|
-
value: mod,
|
|
29
|
-
enumerable: true
|
|
30
|
-
}) : target, mod));
|
|
10
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
31
11
|
|
|
32
12
|
//#endregion
|
|
33
|
-
const __typescript_eslint_utils = __toESM(require("@typescript-eslint/utils"));
|
|
34
|
-
const node_fs = __toESM(require("node:fs"));
|
|
35
|
-
const node_path = __toESM(require("node:path"));
|
|
36
|
-
const __agilebot_eslint_utils = __toESM(require("@agilebot/eslint-utils"));
|
|
37
|
-
const eslint_plugin_react_lib_util_Components_js = __toESM(require("eslint-plugin-react/lib/util/Components.js"));
|
|
38
|
-
|
|
39
13
|
//#region src/util/rule.js
|
|
40
14
|
const docBaseUrl = "https://github.com/sh-agilebot/frontend-toolkit/blob/master/packages/eslint-plugin/src/rules/";
|
|
41
15
|
const hasDocs = [
|
|
@@ -45,7 +19,7 @@ const hasDocs = [
|
|
|
45
19
|
"intl-no-default",
|
|
46
20
|
"react-better-exhaustive-deps"
|
|
47
21
|
];
|
|
48
|
-
const createRule =
|
|
22
|
+
const createRule = ESLintUtils.RuleCreator((name) => hasDocs.includes(name) ? `${docBaseUrl}${name}.md` : `${docBaseUrl}${name}.test.js`);
|
|
49
23
|
|
|
50
24
|
//#endregion
|
|
51
25
|
//#region src/rules/enforce-mui-icon-alias.js
|
|
@@ -67,7 +41,7 @@ var enforce_mui_icon_alias_default = createRule({
|
|
|
67
41
|
return { ImportDeclaration(node) {
|
|
68
42
|
if (node.source.value !== "@mui/icons-material" && node.source.value !== "mdi-material-ui") return;
|
|
69
43
|
for (const specifier of node.specifiers) {
|
|
70
|
-
if (specifier.type !==
|
|
44
|
+
if (specifier.type !== AST_NODE_TYPES.ImportSpecifier) return;
|
|
71
45
|
if (specifier.imported.name === specifier.local.name || !specifier.local.name.endsWith("Icon")) context.report({
|
|
72
46
|
node,
|
|
73
47
|
messageId: "iconAlias",
|
|
@@ -82,15 +56,10 @@ var enforce_mui_icon_alias_default = createRule({
|
|
|
82
56
|
//#endregion
|
|
83
57
|
//#region src/util/context.js
|
|
84
58
|
/**
|
|
85
|
-
|
|
86
59
|
* Get a setting from eslint config
|
|
87
|
-
|
|
88
60
|
* @param {import('eslint').Rule.RuleContext} context - Context
|
|
89
|
-
|
|
90
61
|
* @param {string} name - Name
|
|
91
|
-
|
|
92
62
|
* @returns {*} - result
|
|
93
|
-
|
|
94
63
|
*/
|
|
95
64
|
function getSetting(context, name) {
|
|
96
65
|
return context.settings[`agilebot/${name}`];
|
|
@@ -142,8 +111,8 @@ var import_monorepo_default = createRule({
|
|
|
142
111
|
* @returns {*} node - returns node if it finds the attribute.
|
|
143
112
|
*/
|
|
144
113
|
function findFormatMessageAttrNode(node, attrName) {
|
|
145
|
-
if (node.type ===
|
|
146
|
-
if (node.type ===
|
|
114
|
+
if (node.type === AST_NODE_TYPES.CallExpression && (node.callee.name === "formatMessage" || node.callee.name === "$t") && node.arguments.length > 0 && node.arguments[0].properties) return node.arguments[0].properties.find((a) => a.key && a.key.name === attrName);
|
|
115
|
+
if (node.type === AST_NODE_TYPES.CallExpression && node.callee.type === AST_NODE_TYPES.MemberExpression && (node.callee.object.name === "intl" || node.callee.object.name && node.callee.object.name.endsWith("Intl")) && (node.callee.property.name === "formatMessage" || node.callee.property.name === "$t")) return node.arguments[0].properties.find((a) => a.key && a.key.name === attrName);
|
|
147
116
|
}
|
|
148
117
|
/**
|
|
149
118
|
* Finds an attribute in FormattedMessage using attribute name.
|
|
@@ -152,7 +121,7 @@ function findFormatMessageAttrNode(node, attrName) {
|
|
|
152
121
|
* @returns {*} node - returns node if it finds the attribute.
|
|
153
122
|
*/
|
|
154
123
|
function findFormattedMessageAttrNode(node, attrName) {
|
|
155
|
-
if (node.type ===
|
|
124
|
+
if (node.type === AST_NODE_TYPES.JSXIdentifier && node.name === "FormattedMessage" && node.parent && node.parent.type === AST_NODE_TYPES.JSXOpeningElement) return node.parent.attributes.find((a) => a.name && a.name.name === attrName);
|
|
156
125
|
}
|
|
157
126
|
/**
|
|
158
127
|
* Finds an attribute in defineMessages using attribute name.
|
|
@@ -161,7 +130,7 @@ function findFormattedMessageAttrNode(node, attrName) {
|
|
|
161
130
|
* @returns {*} node - returns node if it finds the attribute.
|
|
162
131
|
*/
|
|
163
132
|
function findAttrNodeInDefineMessages(node, attrName) {
|
|
164
|
-
if (node.type === "Property" && node.key.name === attrName && node.parent && node.parent.parent && node.parent.parent.parent && node.parent.parent.parent.parent && node.parent.parent.parent.parent.type ===
|
|
133
|
+
if (node.type === "Property" && node.key.name === attrName && node.parent && node.parent.parent && node.parent.parent.parent && node.parent.parent.parent.parent && node.parent.parent.parent.parent.type === AST_NODE_TYPES.CallExpression && node.parent.parent.parent.parent.callee.name === "defineMessages") return node;
|
|
165
134
|
}
|
|
166
135
|
/**
|
|
167
136
|
* Finds an attribute in defineMessages using attribute name.
|
|
@@ -170,7 +139,7 @@ function findAttrNodeInDefineMessages(node, attrName) {
|
|
|
170
139
|
* @returns {*} node - returns node if it finds the attribute.
|
|
171
140
|
*/
|
|
172
141
|
function findAttrNodeInDefineMessage(node, attrName) {
|
|
173
|
-
if (node.type === "Property" && node.key.name === attrName && node.parent && node.parent.parent && node.parent.parent.type ===
|
|
142
|
+
if (node.type === "Property" && node.key.name === attrName && node.parent && node.parent.parent && node.parent.parent.type === AST_NODE_TYPES.CallExpression && node.parent.parent.callee.name === "defineMessage") return node;
|
|
174
143
|
}
|
|
175
144
|
/**
|
|
176
145
|
* Returns a sorted array of nodes, based on their starting posting in the locale id.
|
|
@@ -192,23 +161,15 @@ function templateLiteralDisplayStr(node) {
|
|
|
192
161
|
//#endregion
|
|
193
162
|
//#region src/util/translations.js
|
|
194
163
|
/**
|
|
195
|
-
|
|
196
164
|
* Map of locale file paths to keys and modified time
|
|
197
|
-
|
|
198
165
|
* @type {Record<string, {keys: Array<string>, mtime: number}>}
|
|
199
|
-
|
|
200
166
|
*/
|
|
201
167
|
const localeFilesKeys = {};
|
|
202
168
|
/**
|
|
203
|
-
|
|
204
169
|
* Get a list of ids keys from reading locale files
|
|
205
|
-
|
|
206
170
|
* Keeps track of modified times and reloads if changed,; useful for realtime eslint in-editor
|
|
207
|
-
|
|
208
171
|
* @param {import('eslint').Rule.RuleContext} context - Context
|
|
209
|
-
|
|
210
172
|
* @returns {string[]} results - Array of ids
|
|
211
|
-
|
|
212
173
|
*/
|
|
213
174
|
function getIntlIds(context) {
|
|
214
175
|
const projectRoot = getSetting(context, "project-root");
|
|
@@ -216,16 +177,16 @@ function getIntlIds(context) {
|
|
|
216
177
|
if (!localeFiles) throw new Error("localeFiles not in settings");
|
|
217
178
|
const results = [];
|
|
218
179
|
localeFiles.forEach((f) => {
|
|
219
|
-
const fullPath = projectRoot ?
|
|
220
|
-
const mtime =
|
|
180
|
+
const fullPath = projectRoot ? path$1.join(projectRoot, f) : f;
|
|
181
|
+
const mtime = fs.lstatSync(fullPath).mtime.getTime();
|
|
221
182
|
if (!localeFilesKeys[fullPath] || mtime !== localeFilesKeys[fullPath].mtime) {
|
|
222
183
|
let json;
|
|
223
|
-
if (fullPath.endsWith(".json")) json = JSON.parse(
|
|
184
|
+
if (fullPath.endsWith(".json")) json = JSON.parse(fs.readFileSync(fullPath, "utf8"));
|
|
224
185
|
else if (fullPath.endsWith(".ts")) {
|
|
225
|
-
json =
|
|
186
|
+
json = tsImport(fullPath);
|
|
226
187
|
if (typeof json === "object" && json.default) json = json.default;
|
|
227
188
|
} else if (fullPath.endsWith(".js")) {
|
|
228
|
-
json =
|
|
189
|
+
json = __require(fullPath);
|
|
229
190
|
if (typeof json === "object" && json.default) json = json.default;
|
|
230
191
|
} else throw new Error("unsupported file extension");
|
|
231
192
|
localeFilesKeys[fullPath] = {
|
|
@@ -272,17 +233,16 @@ var intl_id_missing_default = createRule({
|
|
|
272
233
|
}
|
|
273
234
|
function processTemplateLiteral(node) {
|
|
274
235
|
const exStr = sortedTemplateElements(node).map((e) => !e.value ? ".*" : e.value.raw).join("");
|
|
275
|
-
|
|
276
|
-
if (!isTemplateTranslated(re)) context.report({
|
|
236
|
+
if (!isTemplateTranslated(new RegExp(exStr))) context.report({
|
|
277
237
|
node,
|
|
278
238
|
messageId: "missingIdPattern",
|
|
279
239
|
data: { value: templateLiteralDisplayStr(node) }
|
|
280
240
|
});
|
|
281
241
|
}
|
|
282
242
|
function processAttrNode(node) {
|
|
283
|
-
if (node.value.type ===
|
|
284
|
-
if (node.value.type ===
|
|
285
|
-
if (node.value.type ===
|
|
243
|
+
if (node.value.type === AST_NODE_TYPES.Literal) return processLiteral(node.value);
|
|
244
|
+
if (node.value.type === AST_NODE_TYPES.JSXExpressionContainer && node.value.expression.type === AST_NODE_TYPES.TemplateLiteral) return processTemplateLiteral(node.value.expression);
|
|
245
|
+
if (node.value.type === AST_NODE_TYPES.TemplateLiteral) return processTemplateLiteral(node.value);
|
|
286
246
|
context.report({
|
|
287
247
|
node,
|
|
288
248
|
messageId: "disallowInvoke",
|
|
@@ -332,10 +292,10 @@ var intl_id_naming_default = createRule({
|
|
|
332
292
|
let isPass;
|
|
333
293
|
for (const v of values) switch (format) {
|
|
334
294
|
case "camelCase":
|
|
335
|
-
if (!
|
|
295
|
+
if (!isCamelCase(v)) isPass = false;
|
|
336
296
|
break;
|
|
337
297
|
case "PascalCase":
|
|
338
|
-
if (!
|
|
298
|
+
if (!isPascalCase(v)) isPass = false;
|
|
339
299
|
break;
|
|
340
300
|
}
|
|
341
301
|
if (isPass === false) context.report({
|
|
@@ -352,9 +312,9 @@ var intl_id_naming_default = createRule({
|
|
|
352
312
|
report(node, displayStr);
|
|
353
313
|
}
|
|
354
314
|
function processAttrNode(node) {
|
|
355
|
-
if (node.value.type ===
|
|
356
|
-
if (node.value.type ===
|
|
357
|
-
if (node.value.type ===
|
|
315
|
+
if (node.value.type === AST_NODE_TYPES.Literal) return processLiteral(node.value);
|
|
316
|
+
if (node.value.type === AST_NODE_TYPES.JSXExpressionContainer && node.value.expression.type === AST_NODE_TYPES.TemplateLiteral) return processTemplateLiteral(node.value.expression);
|
|
317
|
+
if (node.value.type === AST_NODE_TYPES.TemplateLiteral) return processTemplateLiteral(node.value);
|
|
358
318
|
}
|
|
359
319
|
return {
|
|
360
320
|
JSXIdentifier: function(node) {
|
|
@@ -406,9 +366,9 @@ var intl_id_prefix_default = createRule({
|
|
|
406
366
|
report(node, displayStr);
|
|
407
367
|
}
|
|
408
368
|
function processAttrNode(node) {
|
|
409
|
-
if (node.value.type ===
|
|
410
|
-
if (node.value.type ===
|
|
411
|
-
if (node.value.type ===
|
|
369
|
+
if (node.value.type === AST_NODE_TYPES.Literal) return processLiteral(node.value);
|
|
370
|
+
if (node.value.type === AST_NODE_TYPES.JSXExpressionContainer && node.value.expression.type === AST_NODE_TYPES.TemplateLiteral) return processTemplateLiteral(node.value.expression);
|
|
371
|
+
if (node.value.type === AST_NODE_TYPES.TemplateLiteral) return processTemplateLiteral(node.value);
|
|
412
372
|
}
|
|
413
373
|
return {
|
|
414
374
|
JSXIdentifier: function(node) {
|
|
@@ -458,13 +418,12 @@ var intl_id_unused_default = createRule({
|
|
|
458
418
|
}
|
|
459
419
|
function processTemplateLiteral(node) {
|
|
460
420
|
const exStr = sortedTemplateElements(node).map((e) => !e.value ? ".*" : e.value.raw).join("");
|
|
461
|
-
|
|
462
|
-
if (isTemplateTranslated(re)) {}
|
|
421
|
+
if (isTemplateTranslated(new RegExp(exStr))) {}
|
|
463
422
|
}
|
|
464
423
|
function processAttrNode(node) {
|
|
465
|
-
if (node.value.type ===
|
|
466
|
-
if (node.value.type ===
|
|
467
|
-
if (node.value.type ===
|
|
424
|
+
if (node.value.type === AST_NODE_TYPES.Literal) return processLiteral(node.value);
|
|
425
|
+
if (node.value.type === AST_NODE_TYPES.JSXExpressionContainer && node.value.expression.type === AST_NODE_TYPES.TemplateLiteral) return processTemplateLiteral(node.value.expression);
|
|
426
|
+
if (node.value.type === AST_NODE_TYPES.TemplateLiteral) return processTemplateLiteral(node.value);
|
|
468
427
|
}
|
|
469
428
|
return {
|
|
470
429
|
JSXIdentifier: function(node) {
|
|
@@ -481,8 +440,8 @@ var intl_id_unused_default = createRule({
|
|
|
481
440
|
},
|
|
482
441
|
"Program:exit": function() {
|
|
483
442
|
const unusedIds = [...translatedIdSet].filter((id) => !usedIdSet.has(id));
|
|
484
|
-
const jsonPath =
|
|
485
|
-
|
|
443
|
+
const jsonPath = path$1.join(projectRoot, "intl-unused.json");
|
|
444
|
+
fs.writeFileSync(jsonPath, JSON.stringify(unusedIds, null, 2));
|
|
486
445
|
}
|
|
487
446
|
};
|
|
488
447
|
}
|
|
@@ -559,7 +518,7 @@ var no_async_array_methods_default = createRule({
|
|
|
559
518
|
if (!callee || !callee.property || !callee.property.name) return;
|
|
560
519
|
if (notAllowedArrayMethods.includes(callee.property.name)) {
|
|
561
520
|
const functionArguments = node.expression.arguments.find((n) => {
|
|
562
|
-
return [
|
|
521
|
+
return [AST_NODE_TYPES.ArrowFunctionExpression, AST_NODE_TYPES.FunctionExpression].includes(n.type);
|
|
563
522
|
});
|
|
564
523
|
if (functionArguments && functionArguments.async) context.report({
|
|
565
524
|
node,
|
|
@@ -588,7 +547,7 @@ var no_extends_error_default = createRule({
|
|
|
588
547
|
defaultOptions: [],
|
|
589
548
|
create(context) {
|
|
590
549
|
return { ClassDeclaration(node) {
|
|
591
|
-
if (node.superClass && node.superClass.type ===
|
|
550
|
+
if (node.superClass && node.superClass.type === AST_NODE_TYPES.Identifier && node.superClass.name === "Error") context.report({
|
|
592
551
|
node: node.superClass,
|
|
593
552
|
messageId: "noExtendsError"
|
|
594
553
|
});
|
|
@@ -613,7 +572,7 @@ var no_import_css_default = createRule({
|
|
|
613
572
|
defaultOptions: [],
|
|
614
573
|
create(context) {
|
|
615
574
|
return { ImportDeclaration(node) {
|
|
616
|
-
const ext =
|
|
575
|
+
const ext = path.extname(node.source.value);
|
|
617
576
|
if (ext.startsWith(".css") || ext.startsWith(".scss") || ext.startsWith(".sass") || ext.startsWith(".less") || ext.startsWith(".styl")) context.report({
|
|
618
577
|
node,
|
|
619
578
|
messageId: "noImportCSS",
|
|
@@ -643,8 +602,7 @@ var no_then_catch_finally_default = createRule({
|
|
|
643
602
|
},
|
|
644
603
|
defaultOptions: [],
|
|
645
604
|
create(context) {
|
|
646
|
-
const
|
|
647
|
-
const restrictedFunctions = configuration.restrictedFunctions || [];
|
|
605
|
+
const restrictedFunctions = (context.options[0] || {}).restrictedFunctions || [];
|
|
648
606
|
const getScope = typeof context.getScope === "function" ? () => {
|
|
649
607
|
return context.getScope();
|
|
650
608
|
} : (node) => {
|
|
@@ -665,11 +623,11 @@ var no_then_catch_finally_default = createRule({
|
|
|
665
623
|
function isThenCatchFinally(node) {
|
|
666
624
|
return node.property && (node.property.name === "then" || node.property.name === "catch" || node.property.name === "finally");
|
|
667
625
|
}
|
|
668
|
-
return { [`${
|
|
626
|
+
return { [`${AST_NODE_TYPES.CallExpression} > ${AST_NODE_TYPES.MemberExpression}.callee`]: (node) => {
|
|
669
627
|
if (isTopLevelScoped(node)) return;
|
|
670
628
|
if (!isThenCatchFinally(node)) return;
|
|
671
629
|
const callExpression = node.object;
|
|
672
|
-
if (callExpression.type ===
|
|
630
|
+
if (callExpression.type === AST_NODE_TYPES.CallExpression && callExpression.callee.type === AST_NODE_TYPES.Identifier && restrictedFunctions.includes(callExpression.callee.name)) context.report({
|
|
673
631
|
node: node.property,
|
|
674
632
|
messageId: "forbiddenThenCatchFinally",
|
|
675
633
|
data: { name: callExpression.callee.name }
|
|
@@ -1014,12 +972,10 @@ var react_better_exhaustive_deps_default = {
|
|
|
1014
972
|
references.forEach((reference) => {
|
|
1015
973
|
if (setStateInsideEffectWithoutDeps) return;
|
|
1016
974
|
const id = reference.identifier;
|
|
1017
|
-
|
|
1018
|
-
if (!isSetState) return;
|
|
975
|
+
if (!setStateCallSites.has(id)) return;
|
|
1019
976
|
let fnScope = reference.from;
|
|
1020
977
|
while (fnScope.type !== "function") fnScope = fnScope.upper;
|
|
1021
|
-
|
|
1022
|
-
if (isDirectlyInsideEffect) setStateInsideEffectWithoutDeps = key;
|
|
978
|
+
if (fnScope.block === node) setStateInsideEffectWithoutDeps = key;
|
|
1023
979
|
});
|
|
1024
980
|
});
|
|
1025
981
|
if (setStateInsideEffectWithoutDeps) {
|
|
@@ -1051,58 +1007,55 @@ var react_better_exhaustive_deps_default = {
|
|
|
1051
1007
|
node: declaredDependenciesNode,
|
|
1052
1008
|
message: `React Hook ${getSource(reactiveHook)} was passed a dependency list that is not an array literal. This means we can't statically verify whether you've passed the correct dependencies.`
|
|
1053
1009
|
});
|
|
1054
|
-
else {
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
if (declaredDependencyNode.type === "SpreadElement") {
|
|
1059
|
-
reportProblem({
|
|
1060
|
-
node: declaredDependencyNode,
|
|
1061
|
-
message: `React Hook ${getSource(reactiveHook)} has a spread element in its dependency array. This means we can't statically verify whether you've passed the correct dependencies.`
|
|
1062
|
-
});
|
|
1063
|
-
return;
|
|
1064
|
-
}
|
|
1065
|
-
if (useEffectEventVariables.has(declaredDependencyNode)) reportProblem({
|
|
1010
|
+
else (isTSAsArrayExpression ? declaredDependenciesNode.expression : declaredDependenciesNode).elements.forEach((declaredDependencyNode) => {
|
|
1011
|
+
if (declaredDependencyNode == null) return;
|
|
1012
|
+
if (declaredDependencyNode.type === "SpreadElement") {
|
|
1013
|
+
reportProblem({
|
|
1066
1014
|
node: declaredDependencyNode,
|
|
1067
|
-
message: `
|
|
1068
|
-
suggest: [{
|
|
1069
|
-
desc: `Remove the dependency \`${getSource(declaredDependencyNode)}\``,
|
|
1070
|
-
fix(fixer) {
|
|
1071
|
-
return fixer.removeRange(declaredDependencyNode.range);
|
|
1072
|
-
}
|
|
1073
|
-
}]
|
|
1015
|
+
message: `React Hook ${getSource(reactiveHook)} has a spread element in its dependency array. This means we can't statically verify whether you've passed the correct dependencies.`
|
|
1074
1016
|
});
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
else reportProblem({
|
|
1085
|
-
node: declaredDependencyNode,
|
|
1086
|
-
message: `The ${declaredDependencyNode.raw} literal is not a valid dependency because it never changes. You can safely remove it.`
|
|
1087
|
-
});
|
|
1088
|
-
else reportProblem({
|
|
1089
|
-
node: declaredDependencyNode,
|
|
1090
|
-
message: `React Hook ${getSource(reactiveHook)} has a complex expression in the dependency array. Extract it to a separate variable so it can be statically checked.`
|
|
1091
|
-
});
|
|
1092
|
-
return;
|
|
1017
|
+
return;
|
|
1018
|
+
}
|
|
1019
|
+
if (useEffectEventVariables.has(declaredDependencyNode)) reportProblem({
|
|
1020
|
+
node: declaredDependencyNode,
|
|
1021
|
+
message: `Functions returned from \`useEffectEvent\` must not be included in the dependency array. Remove \`${getSource(declaredDependencyNode)}\` from the list.`,
|
|
1022
|
+
suggest: [{
|
|
1023
|
+
desc: `Remove the dependency \`${getSource(declaredDependencyNode)}\``,
|
|
1024
|
+
fix(fixer) {
|
|
1025
|
+
return fixer.removeRange(declaredDependencyNode.range);
|
|
1093
1026
|
}
|
|
1094
|
-
|
|
1027
|
+
}]
|
|
1028
|
+
});
|
|
1029
|
+
let declaredDependency;
|
|
1030
|
+
try {
|
|
1031
|
+
declaredDependency = analyzePropertyChain(declaredDependencyNode, null);
|
|
1032
|
+
} catch (err) {
|
|
1033
|
+
if (/Unsupported node type/.test(err.message)) {
|
|
1034
|
+
if (declaredDependencyNode.type === "Literal") if (dependencies.has(declaredDependencyNode.value)) reportProblem({
|
|
1035
|
+
node: declaredDependencyNode,
|
|
1036
|
+
message: `The ${declaredDependencyNode.raw} literal is not a valid dependency because it never changes. Did you mean to include ${declaredDependencyNode.value} in the array instead?`
|
|
1037
|
+
});
|
|
1038
|
+
else reportProblem({
|
|
1039
|
+
node: declaredDependencyNode,
|
|
1040
|
+
message: `The ${declaredDependencyNode.raw} literal is not a valid dependency because it never changes. You can safely remove it.`
|
|
1041
|
+
});
|
|
1042
|
+
else reportProblem({
|
|
1043
|
+
node: declaredDependencyNode,
|
|
1044
|
+
message: `React Hook ${getSource(reactiveHook)} has a complex expression in the dependency array. Extract it to a separate variable so it can be statically checked.`
|
|
1045
|
+
});
|
|
1046
|
+
return;
|
|
1095
1047
|
}
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1048
|
+
throw err;
|
|
1049
|
+
}
|
|
1050
|
+
let maybeID = declaredDependencyNode;
|
|
1051
|
+
while (maybeID.type === "MemberExpression" || maybeID.type === "OptionalMemberExpression" || maybeID.type === "ChainExpression") maybeID = maybeID.object || maybeID.expression.object;
|
|
1052
|
+
const isDeclaredInComponent = !componentScope.through.some((ref) => ref.identifier === maybeID);
|
|
1053
|
+
declaredDependencies.push({
|
|
1054
|
+
key: declaredDependency,
|
|
1055
|
+
node: declaredDependencyNode
|
|
1104
1056
|
});
|
|
1105
|
-
|
|
1057
|
+
if (!isDeclaredInComponent) externalDependencies.add(declaredDependency);
|
|
1058
|
+
});
|
|
1106
1059
|
const { suggestedDependencies, unnecessaryDependencies, missingDependencies, duplicateDependencies } = collectRecommendations({
|
|
1107
1060
|
dependencies,
|
|
1108
1061
|
declaredDependencies,
|
|
@@ -1111,15 +1064,13 @@ var react_better_exhaustive_deps_default = {
|
|
|
1111
1064
|
isEffect
|
|
1112
1065
|
});
|
|
1113
1066
|
let suggestedDeps = suggestedDependencies;
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
const constructions = scanForConstructions({
|
|
1067
|
+
if (duplicateDependencies.size + missingDependencies.size + unnecessaryDependencies.size === 0) {
|
|
1068
|
+
scanForConstructions({
|
|
1117
1069
|
declaredDependencies,
|
|
1118
1070
|
declaredDependenciesNode,
|
|
1119
1071
|
componentScope,
|
|
1120
1072
|
scope
|
|
1121
|
-
})
|
|
1122
|
-
constructions.forEach(({ construction, isUsedOutsideOfHook, depType }) => {
|
|
1073
|
+
}).forEach(({ construction, isUsedOutsideOfHook, depType }) => {
|
|
1123
1074
|
const wrapperHook = depType === "function" ? "useCallback" : "useMemo";
|
|
1124
1075
|
const constructionType = depType === "function" ? "definition" : "initialization";
|
|
1125
1076
|
const defaultAdvice = `wrap the ${constructionType} of '${construction.name.name}' in its own ${wrapperHook}() Hook.`;
|
|
@@ -1156,8 +1107,8 @@ var react_better_exhaustive_deps_default = {
|
|
|
1156
1107
|
return declaredDepKeys.join(",") === sortedDeclaredDepKeys.join(",");
|
|
1157
1108
|
}
|
|
1158
1109
|
if (areDeclaredDepsAlphabetized()) suggestedDeps.sort();
|
|
1159
|
-
function formatDependency(path$
|
|
1160
|
-
const members = path$
|
|
1110
|
+
function formatDependency(path$2) {
|
|
1111
|
+
const members = path$2.split(".");
|
|
1161
1112
|
let finalPath = "";
|
|
1162
1113
|
for (let i = 0; i < members.length; i++) {
|
|
1163
1114
|
if (i !== 0) {
|
|
@@ -1237,8 +1188,7 @@ var react_better_exhaustive_deps_default = {
|
|
|
1237
1188
|
let setStateRecommendation = null;
|
|
1238
1189
|
missingDependencies.forEach((missingDep) => {
|
|
1239
1190
|
if (setStateRecommendation != null) return;
|
|
1240
|
-
const
|
|
1241
|
-
const references = usedDep.references;
|
|
1191
|
+
const references = dependencies.get(missingDep).references;
|
|
1242
1192
|
let id;
|
|
1243
1193
|
let maybeCall;
|
|
1244
1194
|
for (const reference of references) {
|
|
@@ -1402,8 +1352,8 @@ function collectRecommendations({ dependencies, declaredDependencies, stableDepe
|
|
|
1402
1352
|
const node = getOrCreateNodeByPath(depTree, key);
|
|
1403
1353
|
node.isSatisfiedRecursively = true;
|
|
1404
1354
|
});
|
|
1405
|
-
function getOrCreateNodeByPath(rootNode, path$
|
|
1406
|
-
const keys = path$
|
|
1355
|
+
function getOrCreateNodeByPath(rootNode, path$2) {
|
|
1356
|
+
const keys = path$2.split(".");
|
|
1407
1357
|
let node = rootNode;
|
|
1408
1358
|
for (const key of keys) {
|
|
1409
1359
|
let child = node.children.get(key);
|
|
@@ -1415,8 +1365,8 @@ function collectRecommendations({ dependencies, declaredDependencies, stableDepe
|
|
|
1415
1365
|
}
|
|
1416
1366
|
return node;
|
|
1417
1367
|
}
|
|
1418
|
-
function markAllParentsByPath(rootNode, path$
|
|
1419
|
-
const keys = path$
|
|
1368
|
+
function markAllParentsByPath(rootNode, path$2, fn) {
|
|
1369
|
+
const keys = path$2.split(".");
|
|
1420
1370
|
let node = rootNode;
|
|
1421
1371
|
for (const key of keys) {
|
|
1422
1372
|
const child = node.children.get(key);
|
|
@@ -1430,16 +1380,16 @@ function collectRecommendations({ dependencies, declaredDependencies, stableDepe
|
|
|
1430
1380
|
scanTreeRecursively(depTree, missingDependencies, satisfyingDependencies, (key) => key);
|
|
1431
1381
|
function scanTreeRecursively(node, missingPaths, satisfyingPaths, keyToPath) {
|
|
1432
1382
|
node.children.forEach((child, key) => {
|
|
1433
|
-
const path$
|
|
1383
|
+
const path$2 = keyToPath(key);
|
|
1434
1384
|
if (child.isSatisfiedRecursively) {
|
|
1435
|
-
if (child.isSubtreeUsed) satisfyingPaths.add(path$
|
|
1385
|
+
if (child.isSubtreeUsed) satisfyingPaths.add(path$2);
|
|
1436
1386
|
return;
|
|
1437
1387
|
}
|
|
1438
1388
|
if (child.isUsed) {
|
|
1439
|
-
missingPaths.add(path$
|
|
1389
|
+
missingPaths.add(path$2);
|
|
1440
1390
|
return;
|
|
1441
1391
|
}
|
|
1442
|
-
scanTreeRecursively(child, missingPaths, satisfyingPaths, (childKey) => path$
|
|
1392
|
+
scanTreeRecursively(child, missingPaths, satisfyingPaths, (childKey) => path$2 + "." + childKey);
|
|
1443
1393
|
});
|
|
1444
1394
|
}
|
|
1445
1395
|
const suggestedDependencies = [];
|
|
@@ -1691,12 +1641,10 @@ var react_hook_use_ref_default = createRule({
|
|
|
1691
1641
|
messages: { useRefName: "useRef call is not end with \"Ref\"" }
|
|
1692
1642
|
},
|
|
1693
1643
|
defaultOptions: [],
|
|
1694
|
-
create:
|
|
1695
|
-
|
|
1696
|
-
if (
|
|
1697
|
-
if (node.parent.id.
|
|
1698
|
-
const variable = node.parent.id.name;
|
|
1699
|
-
if (!variable.endsWith("Ref")) context.report({
|
|
1644
|
+
create: Components.default.detect((context, component, util) => ({ CallExpression(node) {
|
|
1645
|
+
if (node.parent && node.parent.type === AST_NODE_TYPES.ReturnStatement || !util.isReactHookCall(node, ["useRef"])) return;
|
|
1646
|
+
if (node.parent.id.type !== AST_NODE_TYPES.Identifier) return;
|
|
1647
|
+
if (!node.parent.id.name.endsWith("Ref")) context.report({
|
|
1700
1648
|
node,
|
|
1701
1649
|
messageId: "useRefName"
|
|
1702
1650
|
});
|
|
@@ -1726,16 +1674,14 @@ var react_prefer_sx_prop_default = createRule({
|
|
|
1726
1674
|
},
|
|
1727
1675
|
defaultOptions: [],
|
|
1728
1676
|
create(context) {
|
|
1729
|
-
const
|
|
1730
|
-
const allowedFor = configuration.allowedFor || [];
|
|
1677
|
+
const allowedFor = (context.options[0] || {}).allowedFor || [];
|
|
1731
1678
|
function checkComponent(node) {
|
|
1732
1679
|
const parentName = node.parent.name;
|
|
1733
1680
|
const tag = parentName.name || `${parentName.object.name}.${parentName.property.name}`;
|
|
1734
1681
|
const componentName = parentName.name || parentName.property.name;
|
|
1735
1682
|
if (componentName && typeof componentName[0] === "string" && componentName[0] !== componentName[0].toUpperCase()) return;
|
|
1736
1683
|
if (allowedFor.includes(tag)) return;
|
|
1737
|
-
|
|
1738
|
-
if (prop === "style") context.report({
|
|
1684
|
+
if (node.name.name === "style") context.report({
|
|
1739
1685
|
node,
|
|
1740
1686
|
messageId: "preferSxProp"
|
|
1741
1687
|
});
|
|
@@ -1744,8 +1690,7 @@ var react_prefer_sx_prop_default = createRule({
|
|
|
1744
1690
|
const tag = node.parent.name.name;
|
|
1745
1691
|
if (!(tag && typeof tag === "string" && tag[0] !== tag[0].toUpperCase())) return;
|
|
1746
1692
|
if (allowedFor.includes(tag)) return;
|
|
1747
|
-
|
|
1748
|
-
if (prop === "style") context.report({
|
|
1693
|
+
if (node.name.name === "style") context.report({
|
|
1749
1694
|
node,
|
|
1750
1695
|
messageId: "preferSxProp"
|
|
1751
1696
|
});
|
|
@@ -1765,9 +1710,9 @@ var react_prefer_sx_prop_default = createRule({
|
|
|
1765
1710
|
* @returns {string | null} The identifier name or null if it can't be determined
|
|
1766
1711
|
*/
|
|
1767
1712
|
function getBasicIdentifier(node) {
|
|
1768
|
-
if (node.type ===
|
|
1769
|
-
if (node.type ===
|
|
1770
|
-
if (node.type ===
|
|
1713
|
+
if (node.type === AST_NODE_TYPES.Identifier) return node.name;
|
|
1714
|
+
if (node.type === AST_NODE_TYPES.Literal) return node.value;
|
|
1715
|
+
if (node.type === AST_NODE_TYPES.TemplateLiteral) {
|
|
1771
1716
|
if (node.expressions.length > 0) return null;
|
|
1772
1717
|
return node.quasis[0].value.raw;
|
|
1773
1718
|
}
|
|
@@ -1780,9 +1725,9 @@ function getBasicIdentifier(node) {
|
|
|
1780
1725
|
*/
|
|
1781
1726
|
function getBaseIdentifier(node) {
|
|
1782
1727
|
switch (node.type) {
|
|
1783
|
-
case
|
|
1784
|
-
case
|
|
1785
|
-
case
|
|
1728
|
+
case AST_NODE_TYPES.Identifier: return node;
|
|
1729
|
+
case AST_NODE_TYPES.CallExpression: return getBaseIdentifier(node.callee);
|
|
1730
|
+
case AST_NODE_TYPES.MemberExpression: return getBaseIdentifier(node.object);
|
|
1786
1731
|
}
|
|
1787
1732
|
return null;
|
|
1788
1733
|
}
|
|
@@ -1793,7 +1738,7 @@ function getBaseIdentifier(node) {
|
|
|
1793
1738
|
*/
|
|
1794
1739
|
function getStyesObj(node) {
|
|
1795
1740
|
const isMakeStyles = node.callee.name === "makeStyles";
|
|
1796
|
-
const isModernApi = node.callee.type ===
|
|
1741
|
+
const isModernApi = node.callee.type === AST_NODE_TYPES.MemberExpression && node.callee.property.name === "create" && getBaseIdentifier(node.callee.object) && getBaseIdentifier(node.callee.object).name === "tss";
|
|
1797
1742
|
if (!isMakeStyles && !isModernApi) return;
|
|
1798
1743
|
const styles = (() => {
|
|
1799
1744
|
if (isMakeStyles) return node.parent.arguments[0];
|
|
@@ -1801,16 +1746,16 @@ function getStyesObj(node) {
|
|
|
1801
1746
|
})();
|
|
1802
1747
|
if (!styles) return;
|
|
1803
1748
|
switch (styles.type) {
|
|
1804
|
-
case
|
|
1805
|
-
case
|
|
1749
|
+
case AST_NODE_TYPES.ObjectExpression: return styles;
|
|
1750
|
+
case AST_NODE_TYPES.ArrowFunctionExpression:
|
|
1806
1751
|
{
|
|
1807
1752
|
const { body } = styles;
|
|
1808
1753
|
switch (body.type) {
|
|
1809
|
-
case
|
|
1810
|
-
case
|
|
1754
|
+
case AST_NODE_TYPES.ObjectExpression: return body;
|
|
1755
|
+
case AST_NODE_TYPES.BlockStatement: {
|
|
1811
1756
|
let stylesObj;
|
|
1812
1757
|
body.body.forEach((bodyNode) => {
|
|
1813
|
-
if (bodyNode.type ===
|
|
1758
|
+
if (bodyNode.type === AST_NODE_TYPES.ReturnStatement && bodyNode.argument.type === AST_NODE_TYPES.ObjectExpression) stylesObj = bodyNode.argument;
|
|
1814
1759
|
});
|
|
1815
1760
|
return stylesObj;
|
|
1816
1761
|
}
|
|
@@ -1826,8 +1771,8 @@ function getStyesObj(node) {
|
|
|
1826
1771
|
* @returns - The styles object or null if it can't be determined
|
|
1827
1772
|
*/
|
|
1828
1773
|
function loopStylesObj(node, callback) {
|
|
1829
|
-
if (node && node.type ===
|
|
1830
|
-
if (property.type ===
|
|
1774
|
+
if (node && node.type === AST_NODE_TYPES.ObjectExpression) node.properties.forEach((property) => {
|
|
1775
|
+
if (property.type === AST_NODE_TYPES.Property && property.value) if (property.value.type === AST_NODE_TYPES.ObjectExpression) loopStylesObj(property.value, callback);
|
|
1831
1776
|
else callback(property.value);
|
|
1832
1777
|
});
|
|
1833
1778
|
}
|
|
@@ -1853,9 +1798,9 @@ var tss_class_naming_default = createRule({
|
|
|
1853
1798
|
if (stylesObj === void 0) return;
|
|
1854
1799
|
stylesObj.properties.forEach((property) => {
|
|
1855
1800
|
if (property.computed) return;
|
|
1856
|
-
if (property.type === "ExperimentalSpreadProperty" || property.type ===
|
|
1801
|
+
if (property.type === "ExperimentalSpreadProperty" || property.type === AST_NODE_TYPES.SpreadElement) return;
|
|
1857
1802
|
const className = property.key.value || property.key.name;
|
|
1858
|
-
if (!
|
|
1803
|
+
if (!isCamelCase(className)) context.report({
|
|
1859
1804
|
node: property,
|
|
1860
1805
|
messageId: "camelCase",
|
|
1861
1806
|
data: { className }
|
|
@@ -2630,7 +2575,7 @@ var tss_no_color_name_default = createRule({
|
|
|
2630
2575
|
const stylesObj = getStyesObj(node);
|
|
2631
2576
|
if (!stylesObj) return;
|
|
2632
2577
|
function checkColorLiteral(value) {
|
|
2633
|
-
if (value.type ===
|
|
2578
|
+
if (value.type === AST_NODE_TYPES.Literal && typeof value.value === "string" && Object.keys(color_name_default).includes(value.value.toLowerCase())) context.report({
|
|
2634
2579
|
node: value,
|
|
2635
2580
|
messageId: "disallowColorName"
|
|
2636
2581
|
});
|
|
@@ -2660,9 +2605,8 @@ var tss_no_color_value_default = createRule({
|
|
|
2660
2605
|
const stylesObj = getStyesObj(node);
|
|
2661
2606
|
if (!stylesObj) return;
|
|
2662
2607
|
function checkColorLiteral(value) {
|
|
2663
|
-
if (value.type ===
|
|
2664
|
-
|
|
2665
|
-
if (colorCodePattern.test(value.value)) context.report({
|
|
2608
|
+
if (value.type === AST_NODE_TYPES.Literal && typeof value.value === "string") {
|
|
2609
|
+
if (/#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})|rgb\?\(\s*(\d{1,3}\s*,\s*){2}\d{1,3}(?:\s*,\s*\d*(?:\.\d+)?)?\s*\)/g.test(value.value)) context.report({
|
|
2666
2610
|
node: value,
|
|
2667
2611
|
messageId: "preferMuiColor"
|
|
2668
2612
|
});
|
|
@@ -2697,12 +2641,12 @@ var tss_unused_classes_default = createRule({
|
|
|
2697
2641
|
if (stylesObj === void 0) return;
|
|
2698
2642
|
stylesObj.properties.forEach((property) => {
|
|
2699
2643
|
if (property.computed) return;
|
|
2700
|
-
if (property.type === "ExperimentalSpreadProperty" || property.type ===
|
|
2644
|
+
if (property.type === "ExperimentalSpreadProperty" || property.type === AST_NODE_TYPES.SpreadElement) return;
|
|
2701
2645
|
definedClasses[property.key.value || property.key.name] = property;
|
|
2702
2646
|
});
|
|
2703
2647
|
},
|
|
2704
2648
|
MemberExpression(node) {
|
|
2705
|
-
if (node.object.type ===
|
|
2649
|
+
if (node.object.type === AST_NODE_TYPES.Identifier && node.object.name === "classes") {
|
|
2706
2650
|
const whichClass = getBasicIdentifier(node.property);
|
|
2707
2651
|
if (whichClass) usedClasses[whichClass] = true;
|
|
2708
2652
|
return;
|
|
@@ -2711,12 +2655,12 @@ var tss_unused_classes_default = createRule({
|
|
|
2711
2655
|
if (!classIdentifier) return;
|
|
2712
2656
|
if (classIdentifier !== "classes") return;
|
|
2713
2657
|
const { parent } = node;
|
|
2714
|
-
if (parent.type !==
|
|
2715
|
-
if (node.object.object && node.object.object.type !==
|
|
2658
|
+
if (parent.type !== AST_NODE_TYPES.MemberExpression) return;
|
|
2659
|
+
if (node.object.object && node.object.object.type !== AST_NODE_TYPES.ThisExpression) return;
|
|
2716
2660
|
const propsIdentifier = getBasicIdentifier(parent.object);
|
|
2717
2661
|
if (propsIdentifier && propsIdentifier !== "props") return;
|
|
2718
|
-
if (!propsIdentifier && parent.object.type !==
|
|
2719
|
-
if (parent.parent.type ===
|
|
2662
|
+
if (!propsIdentifier && parent.object.type !== AST_NODE_TYPES.MemberExpression) return;
|
|
2663
|
+
if (parent.parent.type === AST_NODE_TYPES.MemberExpression) return;
|
|
2720
2664
|
const parentClassIdentifier = getBasicIdentifier(parent.property);
|
|
2721
2665
|
if (parentClassIdentifier) usedClasses[parentClassIdentifier] = true;
|
|
2722
2666
|
},
|
|
@@ -2775,4 +2719,4 @@ Object.keys(rules).forEach((name) => {
|
|
|
2775
2719
|
var src_default = plugin;
|
|
2776
2720
|
|
|
2777
2721
|
//#endregion
|
|
2778
|
-
|
|
2722
|
+
export { src_default as default };
|