eslint 8.57.0 → 9.2.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/README.md +31 -28
- package/bin/eslint.js +4 -3
- package/conf/ecma-version.js +16 -0
- package/conf/globals.js +1 -0
- package/conf/rule-type-list.json +3 -1
- package/lib/api.js +7 -11
- package/lib/cli-engine/cli-engine.js +14 -3
- package/lib/cli-engine/formatters/formatters-meta.json +1 -29
- package/lib/cli-engine/lint-result-cache.js +2 -2
- package/lib/cli.js +115 -36
- package/lib/config/default-config.js +3 -0
- package/lib/config/flat-config-array.js +110 -24
- package/lib/config/flat-config-helpers.js +41 -20
- package/lib/config/flat-config-schema.js +1 -7
- package/lib/config/rule-validator.js +42 -6
- package/lib/eslint/eslint-helpers.js +116 -58
- package/lib/eslint/eslint.js +892 -377
- package/lib/eslint/index.js +2 -2
- package/lib/eslint/legacy-eslint.js +728 -0
- package/lib/linter/apply-disable-directives.js +59 -31
- package/lib/linter/code-path-analysis/code-path-analyzer.js +0 -1
- package/lib/linter/code-path-analysis/code-path.js +32 -30
- package/lib/linter/code-path-analysis/fork-context.js +1 -1
- package/lib/linter/config-comment-parser.js +8 -11
- package/lib/linter/index.js +1 -3
- package/lib/linter/interpolate.js +24 -2
- package/lib/linter/linter.js +428 -207
- package/lib/linter/report-translator.js +3 -3
- package/lib/linter/rules.js +6 -15
- package/lib/linter/source-code-fixer.js +1 -1
- package/lib/linter/timing.js +16 -8
- package/lib/options.js +35 -3
- package/lib/rule-tester/index.js +3 -1
- package/lib/rule-tester/rule-tester.js +424 -347
- package/lib/rules/array-bracket-newline.js +1 -1
- package/lib/rules/array-bracket-spacing.js +1 -1
- package/lib/rules/block-scoped-var.js +1 -1
- package/lib/rules/callback-return.js +2 -2
- package/lib/rules/camelcase.js +3 -5
- package/lib/rules/capitalized-comments.js +10 -7
- package/lib/rules/comma-dangle.js +1 -1
- package/lib/rules/comma-style.js +2 -2
- package/lib/rules/complexity.js +14 -1
- package/lib/rules/constructor-super.js +99 -100
- package/lib/rules/default-case.js +1 -1
- package/lib/rules/eol-last.js +2 -2
- package/lib/rules/function-paren-newline.js +2 -2
- package/lib/rules/indent-legacy.js +5 -5
- package/lib/rules/indent.js +5 -5
- package/lib/rules/index.js +1 -2
- package/lib/rules/key-spacing.js +2 -2
- package/lib/rules/line-comment-position.js +1 -1
- package/lib/rules/lines-around-directive.js +2 -2
- package/lib/rules/max-depth.js +1 -1
- package/lib/rules/max-len.js +3 -3
- package/lib/rules/max-lines.js +3 -3
- package/lib/rules/max-nested-callbacks.js +1 -1
- package/lib/rules/max-params.js +1 -1
- package/lib/rules/max-statements.js +1 -1
- package/lib/rules/multiline-comment-style.js +7 -7
- package/lib/rules/new-cap.js +1 -1
- package/lib/rules/newline-after-var.js +1 -1
- package/lib/rules/newline-before-return.js +1 -1
- package/lib/rules/no-case-declarations.js +13 -1
- package/lib/rules/no-constant-binary-expression.js +7 -8
- package/lib/rules/no-constant-condition.js +18 -7
- package/lib/rules/no-constructor-return.js +2 -2
- package/lib/rules/no-dupe-class-members.js +2 -2
- package/lib/rules/no-else-return.js +1 -1
- package/lib/rules/no-empty-function.js +2 -2
- package/lib/rules/no-empty-static-block.js +1 -1
- package/lib/rules/no-extend-native.js +1 -2
- package/lib/rules/no-extra-semi.js +1 -1
- package/lib/rules/no-fallthrough.js +41 -16
- package/lib/rules/no-implicit-coercion.js +66 -24
- package/lib/rules/no-inner-declarations.js +23 -2
- package/lib/rules/no-invalid-regexp.js +1 -1
- package/lib/rules/no-invalid-this.js +1 -1
- package/lib/rules/no-lone-blocks.js +3 -3
- package/lib/rules/no-loss-of-precision.js +1 -1
- package/lib/rules/no-misleading-character-class.js +225 -69
- package/lib/rules/no-mixed-spaces-and-tabs.js +1 -1
- package/lib/rules/no-multiple-empty-lines.js +1 -1
- package/lib/rules/no-new-native-nonconstructor.js +1 -1
- package/lib/rules/no-new-symbol.js +8 -1
- package/lib/rules/no-restricted-globals.js +1 -1
- package/lib/rules/no-restricted-imports.js +186 -40
- package/lib/rules/no-restricted-modules.js +2 -2
- package/lib/rules/no-return-await.js +1 -1
- package/lib/rules/no-sequences.js +1 -0
- package/lib/rules/no-this-before-super.js +45 -13
- package/lib/rules/no-trailing-spaces.js +2 -3
- package/lib/rules/no-unneeded-ternary.js +1 -1
- package/lib/rules/no-unsafe-optional-chaining.js +1 -1
- package/lib/rules/no-unused-private-class-members.js +1 -1
- package/lib/rules/no-unused-vars.js +197 -36
- package/lib/rules/no-useless-assignment.js +566 -0
- package/lib/rules/no-useless-backreference.js +1 -1
- package/lib/rules/no-useless-computed-key.js +2 -2
- package/lib/rules/no-useless-return.js +7 -2
- package/lib/rules/object-curly-spacing.js +3 -3
- package/lib/rules/object-property-newline.js +1 -1
- package/lib/rules/one-var.js +5 -5
- package/lib/rules/padded-blocks.js +7 -7
- package/lib/rules/prefer-arrow-callback.js +3 -3
- package/lib/rules/prefer-reflect.js +1 -1
- package/lib/rules/prefer-regex-literals.js +1 -1
- package/lib/rules/prefer-template.js +1 -1
- package/lib/rules/radix.js +2 -2
- package/lib/rules/semi-style.js +1 -1
- package/lib/rules/sort-imports.js +1 -1
- package/lib/rules/sort-keys.js +1 -1
- package/lib/rules/sort-vars.js +1 -1
- package/lib/rules/space-unary-ops.js +1 -1
- package/lib/rules/strict.js +1 -1
- package/lib/rules/use-isnan.js +101 -7
- package/lib/rules/utils/ast-utils.js +16 -7
- package/lib/rules/utils/char-source.js +240 -0
- package/lib/rules/utils/lazy-loading-rule-map.js +1 -1
- package/lib/rules/utils/unicode/index.js +9 -4
- package/lib/rules/yield-star-spacing.js +1 -1
- package/lib/shared/runtime-info.js +1 -0
- package/lib/shared/serialization.js +55 -0
- package/lib/shared/stats.js +30 -0
- package/lib/shared/string-utils.js +9 -11
- package/lib/shared/types.js +35 -1
- package/lib/source-code/index.js +3 -1
- package/lib/source-code/source-code.js +299 -85
- package/lib/source-code/token-store/backward-token-cursor.js +3 -3
- package/lib/source-code/token-store/cursors.js +4 -2
- package/lib/source-code/token-store/forward-token-comment-cursor.js +3 -3
- package/lib/source-code/token-store/forward-token-cursor.js +3 -3
- package/lib/source-code/token-store/index.js +2 -2
- package/lib/unsupported-api.js +3 -5
- package/messages/no-config-found.js +1 -1
- package/messages/plugin-conflict.js +1 -1
- package/messages/plugin-invalid.js +1 -1
- package/messages/plugin-missing.js +1 -1
- package/package.json +32 -29
- package/conf/config-schema.js +0 -93
- package/lib/cli-engine/formatters/checkstyle.js +0 -60
- package/lib/cli-engine/formatters/compact.js +0 -60
- package/lib/cli-engine/formatters/jslint-xml.js +0 -41
- package/lib/cli-engine/formatters/junit.js +0 -82
- package/lib/cli-engine/formatters/tap.js +0 -95
- package/lib/cli-engine/formatters/unix.js +0 -58
- package/lib/cli-engine/formatters/visualstudio.js +0 -63
- package/lib/cli-engine/xml-escape.js +0 -34
- package/lib/eslint/flat-eslint.js +0 -1155
- package/lib/rule-tester/flat-rule-tester.js +0 -1131
- package/lib/rules/require-jsdoc.js +0 -122
- package/lib/rules/utils/patterns/letters.js +0 -36
- package/lib/rules/valid-jsdoc.js +0 -516
- package/lib/shared/config-validator.js +0 -347
- package/lib/shared/deprecation-warnings.js +0 -58
- package/lib/shared/relative-module-resolver.js +0 -50
@@ -70,7 +70,7 @@ module.exports = {
|
|
70
70
|
const sourceCode = context.sourceCode;
|
71
71
|
|
72
72
|
// Swallow the final newline, as some editors add it automatically and we don't want it to cause an issue
|
73
|
-
const allLines = sourceCode.lines
|
73
|
+
const allLines = sourceCode.lines.at(-1) === "" ? sourceCode.lines.slice(0, -1) : sourceCode.lines;
|
74
74
|
const templateLiteralLines = new Set();
|
75
75
|
|
76
76
|
//--------------------------------------------------------------------------
|
@@ -1,6 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* @fileoverview Rule to disallow use of the new operator with the `Symbol` object
|
3
3
|
* @author Alberto Rodríguez
|
4
|
+
* @deprecated in ESLint v9.0.0
|
4
5
|
*/
|
5
6
|
|
6
7
|
"use strict";
|
@@ -16,10 +17,16 @@ module.exports = {
|
|
16
17
|
|
17
18
|
docs: {
|
18
19
|
description: "Disallow `new` operators with the `Symbol` object",
|
19
|
-
recommended:
|
20
|
+
recommended: false,
|
20
21
|
url: "https://eslint.org/docs/latest/rules/no-new-symbol"
|
21
22
|
},
|
22
23
|
|
24
|
+
deprecated: true,
|
25
|
+
|
26
|
+
replacedBy: [
|
27
|
+
"no-new-native-nonconstructor"
|
28
|
+
],
|
29
|
+
|
23
30
|
schema: [],
|
24
31
|
|
25
32
|
messages: {
|
@@ -34,10 +34,17 @@ const arrayOfStringsOrObjects = {
|
|
34
34
|
items: {
|
35
35
|
type: "string"
|
36
36
|
}
|
37
|
+
},
|
38
|
+
allowImportNames: {
|
39
|
+
type: "array",
|
40
|
+
items: {
|
41
|
+
type: "string"
|
42
|
+
}
|
37
43
|
}
|
38
44
|
},
|
39
45
|
additionalProperties: false,
|
40
|
-
required: ["name"]
|
46
|
+
required: ["name"],
|
47
|
+
not: { required: ["importNames", "allowImportNames"] }
|
41
48
|
}
|
42
49
|
]
|
43
50
|
},
|
@@ -66,6 +73,14 @@ const arrayOfStringsOrObjectPatterns = {
|
|
66
73
|
minItems: 1,
|
67
74
|
uniqueItems: true
|
68
75
|
},
|
76
|
+
allowImportNames: {
|
77
|
+
type: "array",
|
78
|
+
items: {
|
79
|
+
type: "string"
|
80
|
+
},
|
81
|
+
minItems: 1,
|
82
|
+
uniqueItems: true
|
83
|
+
},
|
69
84
|
group: {
|
70
85
|
type: "array",
|
71
86
|
items: {
|
@@ -77,6 +92,9 @@ const arrayOfStringsOrObjectPatterns = {
|
|
77
92
|
importNamePattern: {
|
78
93
|
type: "string"
|
79
94
|
},
|
95
|
+
allowImportNamePattern: {
|
96
|
+
type: "string"
|
97
|
+
},
|
80
98
|
message: {
|
81
99
|
type: "string",
|
82
100
|
minLength: 1
|
@@ -86,7 +104,16 @@ const arrayOfStringsOrObjectPatterns = {
|
|
86
104
|
}
|
87
105
|
},
|
88
106
|
additionalProperties: false,
|
89
|
-
required: ["group"]
|
107
|
+
required: ["group"],
|
108
|
+
not: {
|
109
|
+
anyOf: [
|
110
|
+
{ required: ["importNames", "allowImportNames"] },
|
111
|
+
{ required: ["importNamePattern", "allowImportNamePattern"] },
|
112
|
+
{ required: ["importNames", "allowImportNamePattern"] },
|
113
|
+
{ required: ["importNamePattern", "allowImportNames"] },
|
114
|
+
{ required: ["allowImportNames", "allowImportNamePattern"] }
|
115
|
+
]
|
116
|
+
}
|
90
117
|
},
|
91
118
|
uniqueItems: true
|
92
119
|
}
|
@@ -131,7 +158,23 @@ module.exports = {
|
|
131
158
|
|
132
159
|
importName: "'{{importName}}' import from '{{importSource}}' is restricted.",
|
133
160
|
// eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
|
134
|
-
importNameWithCustomMessage: "'{{importName}}' import from '{{importSource}}' is restricted. {{customMessage}}"
|
161
|
+
importNameWithCustomMessage: "'{{importName}}' import from '{{importSource}}' is restricted. {{customMessage}}",
|
162
|
+
|
163
|
+
allowedImportName: "'{{importName}}' import from '{{importSource}}' is restricted because only '{{allowedImportNames}}' import(s) is/are allowed.",
|
164
|
+
// eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
|
165
|
+
allowedImportNameWithCustomMessage: "'{{importName}}' import from '{{importSource}}' is restricted because only '{{allowedImportNames}}' import(s) is/are allowed. {{customMessage}}",
|
166
|
+
|
167
|
+
everythingWithAllowImportNames: "* import is invalid because only '{{allowedImportNames}}' from '{{importSource}}' is/are allowed.",
|
168
|
+
// eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
|
169
|
+
everythingWithAllowImportNamesAndCustomMessage: "* import is invalid because only '{{allowedImportNames}}' from '{{importSource}}' is/are allowed. {{customMessage}}",
|
170
|
+
|
171
|
+
allowedImportNamePattern: "'{{importName}}' import from '{{importSource}}' is restricted because only imports that match the pattern '{{allowedImportNamePattern}}' are allowed from '{{importSource}}'.",
|
172
|
+
// eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
|
173
|
+
allowedImportNamePatternWithCustomMessage: "'{{importName}}' import from '{{importSource}}' is restricted because only imports that match the pattern '{{allowedImportNamePattern}}' are allowed from '{{importSource}}'. {{customMessage}}",
|
174
|
+
|
175
|
+
everythingWithAllowedImportNamePattern: "* import is invalid because only imports that match the pattern '{{allowedImportNamePattern}}' from '{{importSource}}' are allowed.",
|
176
|
+
// eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
|
177
|
+
everythingWithAllowedImportNamePatternWithCustomMessage: "* import is invalid because only imports that match the pattern '{{allowedImportNamePattern}}' from '{{importSource}}' are allowed. {{customMessage}}"
|
135
178
|
},
|
136
179
|
|
137
180
|
schema: {
|
@@ -158,20 +201,29 @@ module.exports = {
|
|
158
201
|
const options = Array.isArray(context.options) ? context.options : [];
|
159
202
|
const isPathAndPatternsObject =
|
160
203
|
typeof options[0] === "object" &&
|
161
|
-
(Object.
|
204
|
+
(Object.hasOwn(options[0], "paths") || Object.hasOwn(options[0], "patterns"));
|
162
205
|
|
163
206
|
const restrictedPaths = (isPathAndPatternsObject ? options[0].paths : context.options) || [];
|
164
|
-
const
|
207
|
+
const groupedRestrictedPaths = restrictedPaths.reduce((memo, importSource) => {
|
208
|
+
const path = typeof importSource === "string"
|
209
|
+
? importSource
|
210
|
+
: importSource.name;
|
211
|
+
|
212
|
+
if (!memo[path]) {
|
213
|
+
memo[path] = [];
|
214
|
+
}
|
215
|
+
|
165
216
|
if (typeof importSource === "string") {
|
166
|
-
memo[
|
217
|
+
memo[path].push({});
|
167
218
|
} else {
|
168
|
-
memo[
|
219
|
+
memo[path].push({
|
169
220
|
message: importSource.message,
|
170
|
-
importNames: importSource.importNames
|
171
|
-
|
221
|
+
importNames: importSource.importNames,
|
222
|
+
allowImportNames: importSource.allowImportNames
|
223
|
+
});
|
172
224
|
}
|
173
225
|
return memo;
|
174
|
-
},
|
226
|
+
}, Object.create(null));
|
175
227
|
|
176
228
|
// Handle patterns too, either as strings or groups
|
177
229
|
let restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || [];
|
@@ -182,12 +234,18 @@ module.exports = {
|
|
182
234
|
}
|
183
235
|
|
184
236
|
// relative paths are supported for this rule
|
185
|
-
const restrictedPatternGroups = restrictedPatterns.map(
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
237
|
+
const restrictedPatternGroups = restrictedPatterns.map(
|
238
|
+
({ group, message, caseSensitive, importNames, importNamePattern, allowImportNames, allowImportNamePattern }) => (
|
239
|
+
{
|
240
|
+
matcher: ignore({ allowRelativePaths: true, ignorecase: !caseSensitive }).add(group),
|
241
|
+
customMessage: message,
|
242
|
+
importNames,
|
243
|
+
importNamePattern,
|
244
|
+
allowImportNames,
|
245
|
+
allowImportNamePattern
|
246
|
+
}
|
247
|
+
)
|
248
|
+
);
|
191
249
|
|
192
250
|
// if no imports are restricted we don't need to check
|
193
251
|
if (Object.keys(restrictedPaths).length === 0 && restrictedPatternGroups.length === 0) {
|
@@ -203,33 +261,60 @@ module.exports = {
|
|
203
261
|
* @private
|
204
262
|
*/
|
205
263
|
function checkRestrictedPathAndReport(importSource, importNames, node) {
|
206
|
-
if (!Object.
|
264
|
+
if (!Object.hasOwn(groupedRestrictedPaths, importSource)) {
|
207
265
|
return;
|
208
266
|
}
|
209
267
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
if (importNames.has("*")) {
|
215
|
-
const specifierData = importNames.get("*")[0];
|
268
|
+
groupedRestrictedPaths[importSource].forEach(restrictedPathEntry => {
|
269
|
+
const customMessage = restrictedPathEntry.message;
|
270
|
+
const restrictedImportNames = restrictedPathEntry.importNames;
|
271
|
+
const allowedImportNames = restrictedPathEntry.allowImportNames;
|
216
272
|
|
273
|
+
if (!restrictedImportNames && !allowedImportNames) {
|
217
274
|
context.report({
|
218
275
|
node,
|
219
|
-
messageId: customMessage ? "
|
220
|
-
loc: specifierData.loc,
|
276
|
+
messageId: customMessage ? "pathWithCustomMessage" : "path",
|
221
277
|
data: {
|
222
278
|
importSource,
|
223
|
-
importNames: restrictedImportNames,
|
224
279
|
customMessage
|
225
280
|
}
|
226
281
|
});
|
282
|
+
|
283
|
+
return;
|
227
284
|
}
|
228
285
|
|
229
|
-
|
230
|
-
if (
|
231
|
-
const
|
286
|
+
importNames.forEach((specifiers, importName) => {
|
287
|
+
if (importName === "*") {
|
288
|
+
const [specifier] = specifiers;
|
232
289
|
|
290
|
+
if (restrictedImportNames) {
|
291
|
+
context.report({
|
292
|
+
node,
|
293
|
+
messageId: customMessage ? "everythingWithCustomMessage" : "everything",
|
294
|
+
loc: specifier.loc,
|
295
|
+
data: {
|
296
|
+
importSource,
|
297
|
+
importNames: restrictedImportNames,
|
298
|
+
customMessage
|
299
|
+
}
|
300
|
+
});
|
301
|
+
} else if (allowedImportNames) {
|
302
|
+
context.report({
|
303
|
+
node,
|
304
|
+
messageId: customMessage ? "everythingWithAllowImportNamesAndCustomMessage" : "everythingWithAllowImportNames",
|
305
|
+
loc: specifier.loc,
|
306
|
+
data: {
|
307
|
+
importSource,
|
308
|
+
allowedImportNames,
|
309
|
+
customMessage
|
310
|
+
}
|
311
|
+
});
|
312
|
+
}
|
313
|
+
|
314
|
+
return;
|
315
|
+
}
|
316
|
+
|
317
|
+
if (restrictedImportNames && restrictedImportNames.includes(importName)) {
|
233
318
|
specifiers.forEach(specifier => {
|
234
319
|
context.report({
|
235
320
|
node,
|
@@ -243,17 +328,24 @@ module.exports = {
|
|
243
328
|
});
|
244
329
|
});
|
245
330
|
}
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
331
|
+
|
332
|
+
if (allowedImportNames && !allowedImportNames.includes(importName)) {
|
333
|
+
specifiers.forEach(specifier => {
|
334
|
+
context.report({
|
335
|
+
node,
|
336
|
+
loc: specifier.loc,
|
337
|
+
messageId: customMessage ? "allowedImportNameWithCustomMessage" : "allowedImportName",
|
338
|
+
data: {
|
339
|
+
importSource,
|
340
|
+
customMessage,
|
341
|
+
importName,
|
342
|
+
allowedImportNames
|
343
|
+
}
|
344
|
+
});
|
345
|
+
});
|
254
346
|
}
|
255
347
|
});
|
256
|
-
}
|
348
|
+
});
|
257
349
|
}
|
258
350
|
|
259
351
|
/**
|
@@ -271,12 +363,14 @@ module.exports = {
|
|
271
363
|
const customMessage = group.customMessage;
|
272
364
|
const restrictedImportNames = group.importNames;
|
273
365
|
const restrictedImportNamePattern = group.importNamePattern ? new RegExp(group.importNamePattern, "u") : null;
|
366
|
+
const allowedImportNames = group.allowImportNames;
|
367
|
+
const allowedImportNamePattern = group.allowImportNamePattern ? new RegExp(group.allowImportNamePattern, "u") : null;
|
274
368
|
|
275
|
-
|
369
|
+
/**
|
276
370
|
* If we are not restricting to any specific import names and just the pattern itself,
|
277
371
|
* report the error and move on
|
278
372
|
*/
|
279
|
-
if (!restrictedImportNames && !restrictedImportNamePattern) {
|
373
|
+
if (!restrictedImportNames && !allowedImportNames && !restrictedImportNamePattern && !allowedImportNamePattern) {
|
280
374
|
context.report({
|
281
375
|
node,
|
282
376
|
messageId: customMessage ? "patternWithCustomMessage" : "patterns",
|
@@ -303,6 +397,28 @@ module.exports = {
|
|
303
397
|
customMessage
|
304
398
|
}
|
305
399
|
});
|
400
|
+
} else if (allowedImportNames) {
|
401
|
+
context.report({
|
402
|
+
node,
|
403
|
+
messageId: customMessage ? "everythingWithAllowImportNamesAndCustomMessage" : "everythingWithAllowImportNames",
|
404
|
+
loc: specifier.loc,
|
405
|
+
data: {
|
406
|
+
importSource,
|
407
|
+
allowedImportNames,
|
408
|
+
customMessage
|
409
|
+
}
|
410
|
+
});
|
411
|
+
} else if (allowedImportNamePattern) {
|
412
|
+
context.report({
|
413
|
+
node,
|
414
|
+
messageId: customMessage ? "everythingWithAllowedImportNamePatternWithCustomMessage" : "everythingWithAllowedImportNamePattern",
|
415
|
+
loc: specifier.loc,
|
416
|
+
data: {
|
417
|
+
importSource,
|
418
|
+
allowedImportNamePattern,
|
419
|
+
customMessage
|
420
|
+
}
|
421
|
+
});
|
306
422
|
} else {
|
307
423
|
context.report({
|
308
424
|
node,
|
@@ -336,6 +452,36 @@ module.exports = {
|
|
336
452
|
});
|
337
453
|
});
|
338
454
|
}
|
455
|
+
|
456
|
+
if (allowedImportNames && !allowedImportNames.includes(importName)) {
|
457
|
+
specifiers.forEach(specifier => {
|
458
|
+
context.report({
|
459
|
+
node,
|
460
|
+
messageId: customMessage ? "allowedImportNameWithCustomMessage" : "allowedImportName",
|
461
|
+
loc: specifier.loc,
|
462
|
+
data: {
|
463
|
+
importSource,
|
464
|
+
customMessage,
|
465
|
+
importName,
|
466
|
+
allowedImportNames
|
467
|
+
}
|
468
|
+
});
|
469
|
+
});
|
470
|
+
} else if (allowedImportNamePattern && !allowedImportNamePattern.test(importName)) {
|
471
|
+
specifiers.forEach(specifier => {
|
472
|
+
context.report({
|
473
|
+
node,
|
474
|
+
messageId: customMessage ? "allowedImportNamePatternWithCustomMessage" : "allowedImportNamePattern",
|
475
|
+
loc: specifier.loc,
|
476
|
+
data: {
|
477
|
+
importSource,
|
478
|
+
customMessage,
|
479
|
+
importName,
|
480
|
+
allowedImportNamePattern
|
481
|
+
}
|
482
|
+
});
|
483
|
+
});
|
484
|
+
}
|
339
485
|
});
|
340
486
|
}
|
341
487
|
|
@@ -90,7 +90,7 @@ module.exports = {
|
|
90
90
|
const options = Array.isArray(context.options) ? context.options : [];
|
91
91
|
const isPathAndPatternsObject =
|
92
92
|
typeof options[0] === "object" &&
|
93
|
-
(Object.
|
93
|
+
(Object.hasOwn(options[0], "paths") || Object.hasOwn(options[0], "patterns"));
|
94
94
|
|
95
95
|
const restrictedPaths = (isPathAndPatternsObject ? options[0].paths : context.options) || [];
|
96
96
|
const restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || [];
|
@@ -178,7 +178,7 @@ module.exports = {
|
|
178
178
|
* @private
|
179
179
|
*/
|
180
180
|
function isRestrictedPath(name) {
|
181
|
-
return Object.
|
181
|
+
return Object.hasOwn(restrictedPathMessages, name);
|
182
182
|
}
|
183
183
|
|
184
184
|
return {
|
@@ -118,7 +118,7 @@ module.exports = {
|
|
118
118
|
if (node.parent.type === "LogicalExpression" && node === node.parent.right) {
|
119
119
|
return isInTailCallPosition(node.parent);
|
120
120
|
}
|
121
|
-
if (node.parent.type === "SequenceExpression" && node === node.parent.expressions
|
121
|
+
if (node.parent.type === "SequenceExpression" && node === node.parent.expressions.at(-1)) {
|
122
122
|
return isInTailCallPosition(node.parent);
|
123
123
|
}
|
124
124
|
return false;
|
@@ -30,6 +30,29 @@ function isConstructorFunction(node) {
|
|
30
30
|
);
|
31
31
|
}
|
32
32
|
|
33
|
+
/*
|
34
|
+
* Information for each code path segment.
|
35
|
+
* - superCalled: The flag which shows `super()` called in all code paths.
|
36
|
+
* - invalidNodes: The array of invalid ThisExpression and Super nodes.
|
37
|
+
*/
|
38
|
+
/**
|
39
|
+
*
|
40
|
+
*/
|
41
|
+
class SegmentInfo {
|
42
|
+
|
43
|
+
/**
|
44
|
+
* Indicates whether `super()` is called in all code paths.
|
45
|
+
* @type {boolean}
|
46
|
+
*/
|
47
|
+
superCalled = false;
|
48
|
+
|
49
|
+
/**
|
50
|
+
* The array of invalid ThisExpression and Super nodes.
|
51
|
+
* @type {ASTNode[]}
|
52
|
+
*/
|
53
|
+
invalidNodes = [];
|
54
|
+
}
|
55
|
+
|
33
56
|
//------------------------------------------------------------------------------
|
34
57
|
// Rule Definition
|
35
58
|
//------------------------------------------------------------------------------
|
@@ -64,13 +87,7 @@ module.exports = {
|
|
64
87
|
*/
|
65
88
|
let funcInfo = null;
|
66
89
|
|
67
|
-
|
68
|
-
* Information for each code path segment.
|
69
|
-
* Each key is the id of a code path segment.
|
70
|
-
* Each value is an object:
|
71
|
-
* - superCalled: The flag which shows `super()` called in all code paths.
|
72
|
-
* - invalidNodes: The array of invalid ThisExpression and Super nodes.
|
73
|
-
*/
|
90
|
+
/** @type {Record<string, SegmentInfo>} */
|
74
91
|
let segInfoMap = Object.create(null);
|
75
92
|
|
76
93
|
/**
|
@@ -79,7 +96,7 @@ module.exports = {
|
|
79
96
|
* @returns {boolean} `true` if `super()` is called.
|
80
97
|
*/
|
81
98
|
function isCalled(segment) {
|
82
|
-
return !segment.reachable || segInfoMap[segment.id]
|
99
|
+
return !segment.reachable || segInfoMap[segment.id]?.superCalled;
|
83
100
|
}
|
84
101
|
|
85
102
|
/**
|
@@ -197,11 +214,26 @@ module.exports = {
|
|
197
214
|
return;
|
198
215
|
}
|
199
216
|
|
217
|
+
/**
|
218
|
+
* A collection of nodes to avoid duplicate reports.
|
219
|
+
* @type {Set<ASTNode>}
|
220
|
+
*/
|
221
|
+
const reported = new Set();
|
222
|
+
|
200
223
|
codePath.traverseSegments((segment, controller) => {
|
201
224
|
const info = segInfoMap[segment.id];
|
225
|
+
const invalidNodes = info.invalidNodes
|
226
|
+
.filter(
|
202
227
|
|
203
|
-
|
204
|
-
|
228
|
+
/*
|
229
|
+
* Avoid duplicate reports.
|
230
|
+
* When there is a `finally`, invalidNodes may contain already reported node.
|
231
|
+
*/
|
232
|
+
node => !reported.has(node)
|
233
|
+
);
|
234
|
+
|
235
|
+
for (const invalidNode of invalidNodes) {
|
236
|
+
reported.add(invalidNode);
|
205
237
|
|
206
238
|
context.report({
|
207
239
|
messageId: "noBeforeSuper",
|
@@ -270,18 +302,18 @@ module.exports = {
|
|
270
302
|
funcInfo.codePath.traverseSegments(
|
271
303
|
{ first: toSegment, last: fromSegment },
|
272
304
|
(segment, controller) => {
|
273
|
-
const info = segInfoMap[segment.id];
|
305
|
+
const info = segInfoMap[segment.id] ?? new SegmentInfo();
|
274
306
|
|
275
307
|
if (info.superCalled) {
|
276
|
-
info.invalidNodes = [];
|
277
308
|
controller.skip();
|
278
309
|
} else if (
|
279
310
|
segment.prevSegments.length > 0 &&
|
280
311
|
segment.prevSegments.every(isCalled)
|
281
312
|
) {
|
282
313
|
info.superCalled = true;
|
283
|
-
info.invalidNodes = [];
|
284
314
|
}
|
315
|
+
|
316
|
+
segInfoMap[segment.id] = info;
|
285
317
|
}
|
286
318
|
);
|
287
319
|
},
|
@@ -129,8 +129,7 @@ module.exports = {
|
|
129
129
|
comments = sourceCode.getAllComments(),
|
130
130
|
commentLineNumbers = getCommentLineNumbers(comments);
|
131
131
|
|
132
|
-
let totalLength = 0
|
133
|
-
fixRange = [];
|
132
|
+
let totalLength = 0;
|
134
133
|
|
135
134
|
for (let i = 0, ii = lines.length; i < ii; i++) {
|
136
135
|
const lineNumber = i + 1;
|
@@ -177,7 +176,7 @@ module.exports = {
|
|
177
176
|
continue;
|
178
177
|
}
|
179
178
|
|
180
|
-
fixRange = [rangeStart, rangeEnd];
|
179
|
+
const fixRange = [rangeStart, rangeEnd];
|
181
180
|
|
182
181
|
if (!ignoreComments || !commentLineNumbers.has(lineNumber)) {
|
183
182
|
report(node, location, fixRange);
|
@@ -76,7 +76,7 @@ module.exports = {
|
|
76
76
|
* @returns {string} A string representing an inverted expression
|
77
77
|
*/
|
78
78
|
function invertExpression(node) {
|
79
|
-
if (node.type === "BinaryExpression" && Object.
|
79
|
+
if (node.type === "BinaryExpression" && Object.hasOwn(OPERATOR_INVERSES, node.operator)) {
|
80
80
|
const operatorToken = sourceCode.getFirstTokenBetween(
|
81
81
|
node.left,
|
82
82
|
node.right,
|