eslint 8.47.0 → 8.57.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 +18 -13
- package/bin/eslint.js +38 -5
- package/conf/rule-type-list.json +25 -33
- package/lib/api.js +29 -1
- package/lib/cli-engine/cli-engine.js +2 -2
- package/lib/cli-engine/lint-result-cache.js +18 -6
- package/lib/cli.js +36 -6
- package/lib/config/flat-config-schema.js +124 -61
- package/lib/config/rule-validator.js +2 -1
- package/lib/eslint/eslint-helpers.js +9 -11
- package/lib/eslint/eslint.js +7 -0
- package/lib/eslint/flat-eslint.js +33 -18
- package/lib/linter/apply-disable-directives.js +127 -13
- package/lib/linter/code-path-analysis/code-path-analyzer.js +32 -24
- package/lib/linter/code-path-analysis/code-path-segment.js +52 -24
- package/lib/linter/code-path-analysis/code-path-state.js +1108 -243
- package/lib/linter/code-path-analysis/code-path.js +128 -33
- package/lib/linter/code-path-analysis/fork-context.js +173 -72
- package/lib/linter/config-comment-parser.js +36 -2
- package/lib/linter/linter.js +183 -82
- package/lib/options.js +24 -3
- package/lib/rule-tester/flat-rule-tester.js +113 -25
- package/lib/rule-tester/rule-tester.js +176 -23
- package/lib/rules/array-bracket-newline.js +3 -0
- package/lib/rules/array-bracket-spacing.js +3 -0
- package/lib/rules/array-callback-return.js +175 -25
- package/lib/rules/array-element-newline.js +3 -0
- package/lib/rules/arrow-parens.js +3 -0
- package/lib/rules/arrow-spacing.js +3 -0
- package/lib/rules/block-spacing.js +3 -0
- package/lib/rules/brace-style.js +3 -0
- package/lib/rules/comma-dangle.js +3 -0
- package/lib/rules/comma-spacing.js +3 -0
- package/lib/rules/comma-style.js +3 -0
- package/lib/rules/computed-property-spacing.js +3 -0
- package/lib/rules/consistent-return.js +32 -7
- package/lib/rules/constructor-super.js +37 -14
- package/lib/rules/dot-location.js +3 -0
- package/lib/rules/eol-last.js +3 -0
- package/lib/rules/for-direction.js +38 -24
- package/lib/rules/func-call-spacing.js +3 -0
- package/lib/rules/function-call-argument-newline.js +3 -0
- package/lib/rules/function-paren-newline.js +3 -0
- package/lib/rules/generator-star-spacing.js +3 -0
- package/lib/rules/getter-return.js +33 -8
- package/lib/rules/implicit-arrow-linebreak.js +3 -0
- package/lib/rules/indent.js +3 -0
- package/lib/rules/index.js +1 -0
- package/lib/rules/jsx-quotes.js +3 -0
- package/lib/rules/key-spacing.js +3 -0
- package/lib/rules/keyword-spacing.js +3 -0
- package/lib/rules/linebreak-style.js +3 -0
- package/lib/rules/lines-around-comment.js +3 -0
- package/lib/rules/lines-between-class-members.js +95 -7
- package/lib/rules/logical-assignment-operators.js +31 -3
- package/lib/rules/max-len.js +3 -0
- package/lib/rules/max-statements-per-line.js +3 -0
- package/lib/rules/multiline-ternary.js +3 -0
- package/lib/rules/new-parens.js +3 -0
- package/lib/rules/newline-per-chained-call.js +3 -0
- package/lib/rules/no-array-constructor.js +85 -6
- package/lib/rules/no-confusing-arrow.js +3 -0
- package/lib/rules/no-console.js +74 -2
- package/lib/rules/no-extra-parens.js +3 -0
- package/lib/rules/no-extra-semi.js +3 -0
- package/lib/rules/no-fallthrough.js +42 -14
- package/lib/rules/no-floating-decimal.js +3 -0
- package/lib/rules/no-invalid-this.js +1 -1
- package/lib/rules/no-misleading-character-class.js +65 -15
- package/lib/rules/no-mixed-operators.js +3 -0
- package/lib/rules/no-mixed-spaces-and-tabs.js +3 -0
- package/lib/rules/no-multi-spaces.js +3 -0
- package/lib/rules/no-multiple-empty-lines.js +3 -0
- package/lib/rules/no-new-object.js +7 -0
- package/lib/rules/no-object-constructor.js +117 -0
- package/lib/rules/no-promise-executor-return.js +157 -16
- package/lib/rules/no-prototype-builtins.js +90 -2
- package/lib/rules/no-restricted-imports.js +54 -31
- package/lib/rules/no-restricted-properties.js +15 -28
- package/lib/rules/no-tabs.js +3 -0
- package/lib/rules/no-this-before-super.js +38 -11
- package/lib/rules/no-trailing-spaces.js +3 -0
- package/lib/rules/no-unreachable-loop.js +47 -12
- package/lib/rules/no-unreachable.js +39 -10
- package/lib/rules/no-useless-return.js +35 -4
- package/lib/rules/no-whitespace-before-property.js +3 -0
- package/lib/rules/nonblock-statement-body-position.js +3 -0
- package/lib/rules/object-curly-newline.js +3 -0
- package/lib/rules/object-curly-spacing.js +3 -0
- package/lib/rules/object-property-newline.js +3 -0
- package/lib/rules/one-var-declaration-per-line.js +3 -0
- package/lib/rules/operator-linebreak.js +3 -0
- package/lib/rules/padded-blocks.js +3 -0
- package/lib/rules/padding-line-between-statements.js +3 -0
- package/lib/rules/quote-props.js +3 -0
- package/lib/rules/quotes.js +3 -0
- package/lib/rules/require-atomic-updates.js +21 -7
- package/lib/rules/rest-spread-spacing.js +3 -0
- package/lib/rules/semi-spacing.js +3 -0
- package/lib/rules/semi-style.js +3 -0
- package/lib/rules/semi.js +3 -0
- package/lib/rules/space-before-blocks.js +3 -0
- package/lib/rules/space-before-function-paren.js +3 -0
- package/lib/rules/space-in-parens.js +3 -0
- package/lib/rules/space-infix-ops.js +3 -0
- package/lib/rules/space-unary-ops.js +3 -0
- package/lib/rules/spaced-comment.js +3 -0
- package/lib/rules/switch-colon-spacing.js +3 -0
- package/lib/rules/template-curly-spacing.js +3 -0
- package/lib/rules/template-tag-spacing.js +3 -0
- package/lib/rules/utils/ast-utils.js +111 -1
- package/lib/rules/wrap-iife.js +3 -0
- package/lib/rules/wrap-regex.js +3 -0
- package/lib/rules/yield-star-spacing.js +3 -0
- package/lib/shared/severity.js +49 -0
- package/lib/source-code/source-code.js +329 -3
- package/messages/eslintrc-incompat.js +1 -1
- package/package.json +24 -17
@@ -0,0 +1,117 @@
|
|
1
|
+
/**
|
2
|
+
* @fileoverview Rule to disallow calls to the `Object` constructor without an argument
|
3
|
+
* @author Francesco Trotta
|
4
|
+
*/
|
5
|
+
|
6
|
+
"use strict";
|
7
|
+
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
const {
|
13
|
+
getVariableByName,
|
14
|
+
isArrowToken,
|
15
|
+
isStartOfExpressionStatement,
|
16
|
+
needsPrecedingSemicolon
|
17
|
+
} = require("./utils/ast-utils");
|
18
|
+
|
19
|
+
//------------------------------------------------------------------------------
|
20
|
+
// Rule Definition
|
21
|
+
//------------------------------------------------------------------------------
|
22
|
+
|
23
|
+
/** @type {import('../shared/types').Rule} */
|
24
|
+
module.exports = {
|
25
|
+
meta: {
|
26
|
+
type: "suggestion",
|
27
|
+
|
28
|
+
docs: {
|
29
|
+
description: "Disallow calls to the `Object` constructor without an argument",
|
30
|
+
recommended: false,
|
31
|
+
url: "https://eslint.org/docs/latest/rules/no-object-constructor"
|
32
|
+
},
|
33
|
+
|
34
|
+
hasSuggestions: true,
|
35
|
+
|
36
|
+
schema: [],
|
37
|
+
|
38
|
+
messages: {
|
39
|
+
preferLiteral: "The object literal notation {} is preferable.",
|
40
|
+
useLiteral: "Replace with '{{replacement}}'.",
|
41
|
+
useLiteralAfterSemicolon: "Replace with '{{replacement}}', add preceding semicolon."
|
42
|
+
}
|
43
|
+
},
|
44
|
+
|
45
|
+
create(context) {
|
46
|
+
|
47
|
+
const sourceCode = context.sourceCode;
|
48
|
+
|
49
|
+
/**
|
50
|
+
* Determines whether or not an object literal that replaces a specified node needs to be enclosed in parentheses.
|
51
|
+
* @param {ASTNode} node The node to be replaced.
|
52
|
+
* @returns {boolean} Whether or not parentheses around the object literal are required.
|
53
|
+
*/
|
54
|
+
function needsParentheses(node) {
|
55
|
+
if (isStartOfExpressionStatement(node)) {
|
56
|
+
return true;
|
57
|
+
}
|
58
|
+
|
59
|
+
const prevToken = sourceCode.getTokenBefore(node);
|
60
|
+
|
61
|
+
if (prevToken && isArrowToken(prevToken)) {
|
62
|
+
return true;
|
63
|
+
}
|
64
|
+
|
65
|
+
return false;
|
66
|
+
}
|
67
|
+
|
68
|
+
/**
|
69
|
+
* Reports on nodes where the `Object` constructor is called without arguments.
|
70
|
+
* @param {ASTNode} node The node to evaluate.
|
71
|
+
* @returns {void}
|
72
|
+
*/
|
73
|
+
function check(node) {
|
74
|
+
if (node.callee.type !== "Identifier" || node.callee.name !== "Object" || node.arguments.length) {
|
75
|
+
return;
|
76
|
+
}
|
77
|
+
|
78
|
+
const variable = getVariableByName(sourceCode.getScope(node), "Object");
|
79
|
+
|
80
|
+
if (variable && variable.identifiers.length === 0) {
|
81
|
+
let replacement;
|
82
|
+
let fixText;
|
83
|
+
let messageId = "useLiteral";
|
84
|
+
|
85
|
+
if (needsParentheses(node)) {
|
86
|
+
replacement = "({})";
|
87
|
+
if (needsPrecedingSemicolon(sourceCode, node)) {
|
88
|
+
fixText = ";({})";
|
89
|
+
messageId = "useLiteralAfterSemicolon";
|
90
|
+
} else {
|
91
|
+
fixText = "({})";
|
92
|
+
}
|
93
|
+
} else {
|
94
|
+
replacement = fixText = "{}";
|
95
|
+
}
|
96
|
+
|
97
|
+
context.report({
|
98
|
+
node,
|
99
|
+
messageId: "preferLiteral",
|
100
|
+
suggest: [
|
101
|
+
{
|
102
|
+
messageId,
|
103
|
+
data: { replacement },
|
104
|
+
fix: fixer => fixer.replaceText(node, fixText)
|
105
|
+
}
|
106
|
+
]
|
107
|
+
});
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
return {
|
112
|
+
CallExpression: check,
|
113
|
+
NewExpression: check
|
114
|
+
};
|
115
|
+
|
116
|
+
}
|
117
|
+
};
|
@@ -10,6 +10,7 @@
|
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
12
|
const { findVariable } = require("@eslint-community/eslint-utils");
|
13
|
+
const astUtils = require("./utils/ast-utils");
|
13
14
|
|
14
15
|
//------------------------------------------------------------------------------
|
15
16
|
// Helpers
|
@@ -59,6 +60,78 @@ function isPromiseExecutor(node, scope) {
|
|
59
60
|
isGlobalReference(parent.callee, getOuterScope(scope));
|
60
61
|
}
|
61
62
|
|
63
|
+
/**
|
64
|
+
* Checks if the given node is a void expression.
|
65
|
+
* @param {ASTNode} node The node to check.
|
66
|
+
* @returns {boolean} - `true` if the node is a void expression
|
67
|
+
*/
|
68
|
+
function expressionIsVoid(node) {
|
69
|
+
return node.type === "UnaryExpression" && node.operator === "void";
|
70
|
+
}
|
71
|
+
|
72
|
+
/**
|
73
|
+
* Fixes the linting error by prepending "void " to the given node
|
74
|
+
* @param {Object} sourceCode context given by context.sourceCode
|
75
|
+
* @param {ASTNode} node The node to fix.
|
76
|
+
* @param {Object} fixer The fixer object provided by ESLint.
|
77
|
+
* @returns {Array<Object>} - An array of fix objects to apply to the node.
|
78
|
+
*/
|
79
|
+
function voidPrependFixer(sourceCode, node, fixer) {
|
80
|
+
|
81
|
+
const requiresParens =
|
82
|
+
|
83
|
+
// prepending `void ` will fail if the node has a lower precedence than void
|
84
|
+
astUtils.getPrecedence(node) < astUtils.getPrecedence({ type: "UnaryExpression", operator: "void" }) &&
|
85
|
+
|
86
|
+
// check if there are parentheses around the node to avoid redundant parentheses
|
87
|
+
!astUtils.isParenthesised(sourceCode, node);
|
88
|
+
|
89
|
+
// avoid parentheses issues
|
90
|
+
const returnOrArrowToken = sourceCode.getTokenBefore(
|
91
|
+
node,
|
92
|
+
node.parent.type === "ArrowFunctionExpression"
|
93
|
+
? astUtils.isArrowToken
|
94
|
+
|
95
|
+
// isReturnToken
|
96
|
+
: token => token.type === "Keyword" && token.value === "return"
|
97
|
+
);
|
98
|
+
|
99
|
+
const firstToken = sourceCode.getTokenAfter(returnOrArrowToken);
|
100
|
+
|
101
|
+
const prependSpace =
|
102
|
+
|
103
|
+
// is return token, as => allows void to be adjacent
|
104
|
+
returnOrArrowToken.value === "return" &&
|
105
|
+
|
106
|
+
// If two tokens (return and "(") are adjacent
|
107
|
+
returnOrArrowToken.range[1] === firstToken.range[0];
|
108
|
+
|
109
|
+
return [
|
110
|
+
fixer.insertTextBefore(firstToken, `${prependSpace ? " " : ""}void ${requiresParens ? "(" : ""}`),
|
111
|
+
fixer.insertTextAfter(node, requiresParens ? ")" : "")
|
112
|
+
];
|
113
|
+
}
|
114
|
+
|
115
|
+
/**
|
116
|
+
* Fixes the linting error by `wrapping {}` around the given node's body.
|
117
|
+
* @param {Object} sourceCode context given by context.sourceCode
|
118
|
+
* @param {ASTNode} node The node to fix.
|
119
|
+
* @param {Object} fixer The fixer object provided by ESLint.
|
120
|
+
* @returns {Array<Object>} - An array of fix objects to apply to the node.
|
121
|
+
*/
|
122
|
+
function curlyWrapFixer(sourceCode, node, fixer) {
|
123
|
+
|
124
|
+
// https://github.com/eslint/eslint/pull/17282#issuecomment-1592795923
|
125
|
+
const arrowToken = sourceCode.getTokenBefore(node.body, astUtils.isArrowToken);
|
126
|
+
const firstToken = sourceCode.getTokenAfter(arrowToken);
|
127
|
+
const lastToken = sourceCode.getLastToken(node);
|
128
|
+
|
129
|
+
return [
|
130
|
+
fixer.insertTextBefore(firstToken, "{"),
|
131
|
+
fixer.insertTextAfter(lastToken, "}")
|
132
|
+
];
|
133
|
+
}
|
134
|
+
|
62
135
|
//------------------------------------------------------------------------------
|
63
136
|
// Rule Definition
|
64
137
|
//------------------------------------------------------------------------------
|
@@ -74,10 +147,27 @@ module.exports = {
|
|
74
147
|
url: "https://eslint.org/docs/latest/rules/no-promise-executor-return"
|
75
148
|
},
|
76
149
|
|
77
|
-
|
150
|
+
hasSuggestions: true,
|
151
|
+
|
152
|
+
schema: [{
|
153
|
+
type: "object",
|
154
|
+
properties: {
|
155
|
+
allowVoid: {
|
156
|
+
type: "boolean",
|
157
|
+
default: false
|
158
|
+
}
|
159
|
+
},
|
160
|
+
additionalProperties: false
|
161
|
+
}],
|
78
162
|
|
79
163
|
messages: {
|
80
|
-
returnsValue: "Return values from promise executor functions cannot be read."
|
164
|
+
returnsValue: "Return values from promise executor functions cannot be read.",
|
165
|
+
|
166
|
+
// arrow and function suggestions
|
167
|
+
prependVoid: "Prepend `void` to the expression.",
|
168
|
+
|
169
|
+
// only arrow suggestions
|
170
|
+
wrapBraces: "Wrap the expression in `{}`."
|
81
171
|
}
|
82
172
|
},
|
83
173
|
|
@@ -85,26 +175,55 @@ module.exports = {
|
|
85
175
|
|
86
176
|
let funcInfo = null;
|
87
177
|
const sourceCode = context.sourceCode;
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
* @param {ASTNode} node Node to report.
|
92
|
-
* @returns {void}
|
93
|
-
*/
|
94
|
-
function report(node) {
|
95
|
-
context.report({ node, messageId: "returnsValue" });
|
96
|
-
}
|
178
|
+
const {
|
179
|
+
allowVoid = false
|
180
|
+
} = context.options[0] || {};
|
97
181
|
|
98
182
|
return {
|
99
183
|
|
100
184
|
onCodePathStart(_, node) {
|
101
185
|
funcInfo = {
|
102
186
|
upper: funcInfo,
|
103
|
-
shouldCheck:
|
187
|
+
shouldCheck:
|
188
|
+
functionTypesToCheck.has(node.type) &&
|
189
|
+
isPromiseExecutor(node, sourceCode.getScope(node))
|
104
190
|
};
|
105
191
|
|
106
|
-
if (
|
107
|
-
|
192
|
+
if (// Is a Promise executor
|
193
|
+
funcInfo.shouldCheck &&
|
194
|
+
node.type === "ArrowFunctionExpression" &&
|
195
|
+
node.expression &&
|
196
|
+
|
197
|
+
// Except void
|
198
|
+
!(allowVoid && expressionIsVoid(node.body))
|
199
|
+
) {
|
200
|
+
const suggest = [];
|
201
|
+
|
202
|
+
// prevent useless refactors
|
203
|
+
if (allowVoid) {
|
204
|
+
suggest.push({
|
205
|
+
messageId: "prependVoid",
|
206
|
+
fix(fixer) {
|
207
|
+
return voidPrependFixer(sourceCode, node.body, fixer);
|
208
|
+
}
|
209
|
+
});
|
210
|
+
}
|
211
|
+
|
212
|
+
// Do not suggest wrapping an unnamed FunctionExpression in braces as that would be invalid syntax.
|
213
|
+
if (!(node.body.type === "FunctionExpression" && !node.body.id)) {
|
214
|
+
suggest.push({
|
215
|
+
messageId: "wrapBraces",
|
216
|
+
fix(fixer) {
|
217
|
+
return curlyWrapFixer(sourceCode, node, fixer);
|
218
|
+
}
|
219
|
+
});
|
220
|
+
}
|
221
|
+
|
222
|
+
context.report({
|
223
|
+
node: node.body,
|
224
|
+
messageId: "returnsValue",
|
225
|
+
suggest
|
226
|
+
});
|
108
227
|
}
|
109
228
|
},
|
110
229
|
|
@@ -113,9 +232,31 @@ module.exports = {
|
|
113
232
|
},
|
114
233
|
|
115
234
|
ReturnStatement(node) {
|
116
|
-
if (funcInfo.shouldCheck && node.argument) {
|
117
|
-
|
235
|
+
if (!(funcInfo.shouldCheck && node.argument)) {
|
236
|
+
return;
|
118
237
|
}
|
238
|
+
|
239
|
+
// node is `return <expression>`
|
240
|
+
if (!allowVoid) {
|
241
|
+
context.report({ node, messageId: "returnsValue" });
|
242
|
+
return;
|
243
|
+
}
|
244
|
+
|
245
|
+
if (expressionIsVoid(node.argument)) {
|
246
|
+
return;
|
247
|
+
}
|
248
|
+
|
249
|
+
// allowVoid && !expressionIsVoid
|
250
|
+
context.report({
|
251
|
+
node,
|
252
|
+
messageId: "returnsValue",
|
253
|
+
suggest: [{
|
254
|
+
messageId: "prependVoid",
|
255
|
+
fix(fixer) {
|
256
|
+
return voidPrependFixer(sourceCode, node.argument, fixer);
|
257
|
+
}
|
258
|
+
}]
|
259
|
+
});
|
119
260
|
}
|
120
261
|
};
|
121
262
|
}
|
@@ -10,6 +10,37 @@
|
|
10
10
|
|
11
11
|
const astUtils = require("./utils/ast-utils");
|
12
12
|
|
13
|
+
//------------------------------------------------------------------------------
|
14
|
+
// Helpers
|
15
|
+
//------------------------------------------------------------------------------
|
16
|
+
|
17
|
+
/**
|
18
|
+
* Returns true if the node or any of the objects
|
19
|
+
* to the left of it in the member/call chain is optional.
|
20
|
+
*
|
21
|
+
* e.g. `a?.b`, `a?.b.c`, `a?.()`, `a()?.()`
|
22
|
+
* @param {ASTNode} node The expression to check
|
23
|
+
* @returns {boolean} `true` if there is a short-circuiting optional `?.`
|
24
|
+
* in the same option chain to the left of this call or member expression,
|
25
|
+
* or the node itself is an optional call or member `?.`.
|
26
|
+
*/
|
27
|
+
function isAfterOptional(node) {
|
28
|
+
let leftNode;
|
29
|
+
|
30
|
+
if (node.type === "MemberExpression") {
|
31
|
+
leftNode = node.object;
|
32
|
+
} else if (node.type === "CallExpression") {
|
33
|
+
leftNode = node.callee;
|
34
|
+
} else {
|
35
|
+
return false;
|
36
|
+
}
|
37
|
+
if (node.optional) {
|
38
|
+
return true;
|
39
|
+
}
|
40
|
+
return isAfterOptional(leftNode);
|
41
|
+
}
|
42
|
+
|
43
|
+
|
13
44
|
//------------------------------------------------------------------------------
|
14
45
|
// Rule Definition
|
15
46
|
//------------------------------------------------------------------------------
|
@@ -25,10 +56,13 @@ module.exports = {
|
|
25
56
|
url: "https://eslint.org/docs/latest/rules/no-prototype-builtins"
|
26
57
|
},
|
27
58
|
|
59
|
+
hasSuggestions: true,
|
60
|
+
|
28
61
|
schema: [],
|
29
62
|
|
30
63
|
messages: {
|
31
|
-
prototypeBuildIn: "Do not access Object.prototype method '{{prop}}' from target object."
|
64
|
+
prototypeBuildIn: "Do not access Object.prototype method '{{prop}}' from target object.",
|
65
|
+
callObjectPrototype: "Call Object.prototype.{{prop}} explicitly."
|
32
66
|
}
|
33
67
|
},
|
34
68
|
|
@@ -59,7 +93,61 @@ module.exports = {
|
|
59
93
|
messageId: "prototypeBuildIn",
|
60
94
|
loc: callee.property.loc,
|
61
95
|
data: { prop: propName },
|
62
|
-
node
|
96
|
+
node,
|
97
|
+
suggest: [
|
98
|
+
{
|
99
|
+
messageId: "callObjectPrototype",
|
100
|
+
data: { prop: propName },
|
101
|
+
fix(fixer) {
|
102
|
+
const sourceCode = context.sourceCode;
|
103
|
+
|
104
|
+
/*
|
105
|
+
* A call after an optional chain (e.g. a?.b.hasOwnProperty(c))
|
106
|
+
* must be fixed manually because the call can be short-circuited
|
107
|
+
*/
|
108
|
+
if (isAfterOptional(node)) {
|
109
|
+
return null;
|
110
|
+
}
|
111
|
+
|
112
|
+
/*
|
113
|
+
* A call on a ChainExpression (e.g. (a?.hasOwnProperty)(c)) will trigger
|
114
|
+
* no-unsafe-optional-chaining which should be fixed before this suggestion
|
115
|
+
*/
|
116
|
+
if (node.callee.type === "ChainExpression") {
|
117
|
+
return null;
|
118
|
+
}
|
119
|
+
|
120
|
+
const objectVariable = astUtils.getVariableByName(sourceCode.getScope(node), "Object");
|
121
|
+
|
122
|
+
/*
|
123
|
+
* We can't use Object if the global Object was shadowed,
|
124
|
+
* or Object does not exist in the global scope for some reason
|
125
|
+
*/
|
126
|
+
if (!objectVariable || objectVariable.scope.type !== "global" || objectVariable.defs.length > 0) {
|
127
|
+
return null;
|
128
|
+
}
|
129
|
+
|
130
|
+
let objectText = sourceCode.getText(callee.object);
|
131
|
+
|
132
|
+
if (astUtils.getPrecedence(callee.object) <= astUtils.getPrecedence({ type: "SequenceExpression" })) {
|
133
|
+
objectText = `(${objectText})`;
|
134
|
+
}
|
135
|
+
|
136
|
+
const openParenToken = sourceCode.getTokenAfter(
|
137
|
+
node.callee,
|
138
|
+
astUtils.isOpeningParenToken
|
139
|
+
);
|
140
|
+
const isEmptyParameters = node.arguments.length === 0;
|
141
|
+
const delim = isEmptyParameters ? "" : ", ";
|
142
|
+
const fixes = [
|
143
|
+
fixer.replaceText(callee, `Object.prototype.${propName}.call`),
|
144
|
+
fixer.insertTextAfter(openParenToken, objectText + delim)
|
145
|
+
];
|
146
|
+
|
147
|
+
return fixes;
|
148
|
+
}
|
149
|
+
}
|
150
|
+
]
|
63
151
|
});
|
64
152
|
}
|
65
153
|
}
|
@@ -74,6 +74,9 @@ const arrayOfStringsOrObjectPatterns = {
|
|
74
74
|
minItems: 1,
|
75
75
|
uniqueItems: true
|
76
76
|
},
|
77
|
+
importNamePattern: {
|
78
|
+
type: "string"
|
79
|
+
},
|
77
80
|
message: {
|
78
81
|
type: "string",
|
79
82
|
minLength: 1
|
@@ -115,8 +118,12 @@ module.exports = {
|
|
115
118
|
patternAndImportNameWithCustomMessage: "'{{importName}}' import from '{{importSource}}' is restricted from being used by a pattern. {{customMessage}}",
|
116
119
|
|
117
120
|
patternAndEverything: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted from being used by a pattern.",
|
121
|
+
|
122
|
+
patternAndEverythingWithRegexImportName: "* import is invalid because import name matching '{{importNames}}' pattern from '{{importSource}}' is restricted from being used.",
|
118
123
|
// eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
|
119
124
|
patternAndEverythingWithCustomMessage: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted from being used by a pattern. {{customMessage}}",
|
125
|
+
// eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
|
126
|
+
patternAndEverythingWithRegexImportNameAndCustomMessage: "* import is invalid because import name matching '{{importNames}}' pattern from '{{importSource}}' is restricted from being used. {{customMessage}}",
|
120
127
|
|
121
128
|
everything: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted.",
|
122
129
|
// eslint-disable-next-line eslint-plugin/report-message-format -- Custom message might not end in a period
|
@@ -175,10 +182,11 @@ module.exports = {
|
|
175
182
|
}
|
176
183
|
|
177
184
|
// relative paths are supported for this rule
|
178
|
-
const restrictedPatternGroups = restrictedPatterns.map(({ group, message, caseSensitive, importNames }) => ({
|
185
|
+
const restrictedPatternGroups = restrictedPatterns.map(({ group, message, caseSensitive, importNames, importNamePattern }) => ({
|
179
186
|
matcher: ignore({ allowRelativePaths: true, ignorecase: !caseSensitive }).add(group),
|
180
187
|
customMessage: message,
|
181
|
-
importNames
|
188
|
+
importNames,
|
189
|
+
importNamePattern
|
182
190
|
}));
|
183
191
|
|
184
192
|
// if no imports are restricted we don't need to check
|
@@ -262,12 +270,13 @@ module.exports = {
|
|
262
270
|
|
263
271
|
const customMessage = group.customMessage;
|
264
272
|
const restrictedImportNames = group.importNames;
|
273
|
+
const restrictedImportNamePattern = group.importNamePattern ? new RegExp(group.importNamePattern, "u") : null;
|
265
274
|
|
266
275
|
/*
|
267
276
|
* If we are not restricting to any specific import names and just the pattern itself,
|
268
277
|
* report the error and move on
|
269
278
|
*/
|
270
|
-
if (!restrictedImportNames) {
|
279
|
+
if (!restrictedImportNames && !restrictedImportNamePattern) {
|
271
280
|
context.report({
|
272
281
|
node,
|
273
282
|
messageId: customMessage ? "patternWithCustomMessage" : "patterns",
|
@@ -279,40 +288,54 @@ module.exports = {
|
|
279
288
|
return;
|
280
289
|
}
|
281
290
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
291
|
+
importNames.forEach((specifiers, importName) => {
|
292
|
+
if (importName === "*") {
|
293
|
+
const [specifier] = specifiers;
|
294
|
+
|
295
|
+
if (restrictedImportNames) {
|
296
|
+
context.report({
|
297
|
+
node,
|
298
|
+
messageId: customMessage ? "patternAndEverythingWithCustomMessage" : "patternAndEverything",
|
299
|
+
loc: specifier.loc,
|
300
|
+
data: {
|
301
|
+
importSource,
|
302
|
+
importNames: restrictedImportNames,
|
303
|
+
customMessage
|
304
|
+
}
|
305
|
+
});
|
306
|
+
} else {
|
307
|
+
context.report({
|
308
|
+
node,
|
309
|
+
messageId: customMessage ? "patternAndEverythingWithRegexImportNameAndCustomMessage" : "patternAndEverythingWithRegexImportName",
|
310
|
+
loc: specifier.loc,
|
311
|
+
data: {
|
312
|
+
importSource,
|
313
|
+
importNames: restrictedImportNamePattern,
|
314
|
+
customMessage
|
315
|
+
}
|
316
|
+
});
|
293
317
|
}
|
294
|
-
});
|
295
|
-
}
|
296
318
|
|
297
|
-
restrictedImportNames.forEach(importName => {
|
298
|
-
if (!importNames.has(importName)) {
|
299
319
|
return;
|
300
320
|
}
|
301
321
|
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
322
|
+
if (
|
323
|
+
(restrictedImportNames && restrictedImportNames.includes(importName)) ||
|
324
|
+
(restrictedImportNamePattern && restrictedImportNamePattern.test(importName))
|
325
|
+
) {
|
326
|
+
specifiers.forEach(specifier => {
|
327
|
+
context.report({
|
328
|
+
node,
|
329
|
+
messageId: customMessage ? "patternAndImportNameWithCustomMessage" : "patternAndImportName",
|
330
|
+
loc: specifier.loc,
|
331
|
+
data: {
|
332
|
+
importSource,
|
333
|
+
customMessage,
|
334
|
+
importName
|
335
|
+
}
|
336
|
+
});
|
314
337
|
});
|
315
|
-
}
|
338
|
+
}
|
316
339
|
});
|
317
340
|
}
|
318
341
|
|
@@ -142,40 +142,27 @@ module.exports = {
|
|
142
142
|
}
|
143
143
|
}
|
144
144
|
|
145
|
-
/**
|
146
|
-
* Checks property accesses in a destructuring assignment expression, e.g. `var foo; ({foo} = bar);`
|
147
|
-
* @param {ASTNode} node An AssignmentExpression or AssignmentPattern node
|
148
|
-
* @returns {undefined}
|
149
|
-
*/
|
150
|
-
function checkDestructuringAssignment(node) {
|
151
|
-
if (node.right.type === "Identifier") {
|
152
|
-
const objectName = node.right.name;
|
153
|
-
|
154
|
-
if (node.left.type === "ObjectPattern") {
|
155
|
-
node.left.properties.forEach(property => {
|
156
|
-
checkPropertyAccess(node.left, objectName, astUtils.getStaticPropertyName(property));
|
157
|
-
});
|
158
|
-
}
|
159
|
-
}
|
160
|
-
}
|
161
|
-
|
162
145
|
return {
|
163
146
|
MemberExpression(node) {
|
164
147
|
checkPropertyAccess(node, node.object && node.object.name, astUtils.getStaticPropertyName(node));
|
165
148
|
},
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
if (node.
|
171
|
-
node.
|
172
|
-
|
173
|
-
|
149
|
+
ObjectPattern(node) {
|
150
|
+
let objectName = null;
|
151
|
+
|
152
|
+
if (node.parent.type === "VariableDeclarator") {
|
153
|
+
if (node.parent.init && node.parent.init.type === "Identifier") {
|
154
|
+
objectName = node.parent.init.name;
|
155
|
+
}
|
156
|
+
} else if (node.parent.type === "AssignmentExpression" || node.parent.type === "AssignmentPattern") {
|
157
|
+
if (node.parent.right.type === "Identifier") {
|
158
|
+
objectName = node.parent.right.name;
|
174
159
|
}
|
175
160
|
}
|
176
|
-
|
177
|
-
|
178
|
-
|
161
|
+
|
162
|
+
node.properties.forEach(property => {
|
163
|
+
checkPropertyAccess(node, objectName, astUtils.getStaticPropertyName(property));
|
164
|
+
});
|
165
|
+
}
|
179
166
|
};
|
180
167
|
}
|
181
168
|
};
|
package/lib/rules/no-tabs.js
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* @fileoverview Rule to check for tabs inside a file
|
3
3
|
* @author Gyandeep Singh
|
4
|
+
* @deprecated in ESLint v8.53.0
|
4
5
|
*/
|
5
6
|
|
6
7
|
"use strict";
|
@@ -19,6 +20,8 @@ const anyNonWhitespaceRegex = /\S/u;
|
|
19
20
|
/** @type {import('../shared/types').Rule} */
|
20
21
|
module.exports = {
|
21
22
|
meta: {
|
23
|
+
deprecated: true,
|
24
|
+
replacedBy: [],
|
22
25
|
type: "layout",
|
23
26
|
|
24
27
|
docs: {
|