eslint 8.52.0 → 8.54.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 +1 -1
- package/bin/eslint.js +24 -2
- package/lib/cli-engine/lint-result-cache.js +18 -6
- package/lib/linter/linter.js +2 -2
- package/lib/rules/array-bracket-newline.js +3 -0
- package/lib/rules/array-bracket-spacing.js +3 -0
- 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/dot-location.js +3 -0
- package/lib/rules/eol-last.js +3 -0
- package/lib/rules/for-direction.js +23 -16
- 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/implicit-arrow-linebreak.js +3 -0
- package/lib/rules/indent.js +3 -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 +3 -0
- 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-floating-decimal.js +3 -0
- 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-object-constructor.js +7 -106
- package/lib/rules/no-prototype-builtins.js +90 -2
- package/lib/rules/no-tabs.js +3 -0
- package/lib/rules/no-trailing-spaces.js +3 -0
- 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/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/package.json +8 -8
package/lib/rules/new-parens.js
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* @fileoverview Rule to flag when using constructor without parentheses
|
3
3
|
* @author Ilya Volodin
|
4
|
+
* @deprecated in ESLint v8.53.0
|
4
5
|
*/
|
5
6
|
|
6
7
|
"use strict";
|
@@ -22,6 +23,8 @@ const astUtils = require("./utils/ast-utils");
|
|
22
23
|
/** @type {import('../shared/types').Rule} */
|
23
24
|
module.exports = {
|
24
25
|
meta: {
|
26
|
+
deprecated: true,
|
27
|
+
replacedBy: [],
|
25
28
|
type: "layout",
|
26
29
|
|
27
30
|
docs: {
|
@@ -2,6 +2,7 @@
|
|
2
2
|
* @fileoverview Rule to ensure newline per method call when chaining calls
|
3
3
|
* @author Rajendra Patil
|
4
4
|
* @author Burak Yigit Kaya
|
5
|
+
* @deprecated in ESLint v8.53.0
|
5
6
|
*/
|
6
7
|
|
7
8
|
"use strict";
|
@@ -15,6 +16,8 @@ const astUtils = require("./utils/ast-utils");
|
|
15
16
|
/** @type {import('../shared/types').Rule} */
|
16
17
|
module.exports = {
|
17
18
|
meta: {
|
19
|
+
deprecated: true,
|
20
|
+
replacedBy: [],
|
18
21
|
type: "layout",
|
19
22
|
|
20
23
|
docs: {
|
@@ -5,6 +5,18 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
const {
|
13
|
+
getVariableByName,
|
14
|
+
isClosingParenToken,
|
15
|
+
isOpeningParenToken,
|
16
|
+
isStartOfExpressionStatement,
|
17
|
+
needsPrecedingSemicolon
|
18
|
+
} = require("./utils/ast-utils");
|
19
|
+
|
8
20
|
//------------------------------------------------------------------------------
|
9
21
|
// Rule Definition
|
10
22
|
//------------------------------------------------------------------------------
|
@@ -20,15 +32,45 @@ module.exports = {
|
|
20
32
|
url: "https://eslint.org/docs/latest/rules/no-array-constructor"
|
21
33
|
},
|
22
34
|
|
35
|
+
hasSuggestions: true,
|
36
|
+
|
23
37
|
schema: [],
|
24
38
|
|
25
39
|
messages: {
|
26
|
-
preferLiteral: "The array literal notation [] is preferable."
|
40
|
+
preferLiteral: "The array literal notation [] is preferable.",
|
41
|
+
useLiteral: "Replace with an array literal.",
|
42
|
+
useLiteralAfterSemicolon: "Replace with an array literal, add preceding semicolon."
|
27
43
|
}
|
28
44
|
},
|
29
45
|
|
30
46
|
create(context) {
|
31
47
|
|
48
|
+
const sourceCode = context.sourceCode;
|
49
|
+
|
50
|
+
/**
|
51
|
+
* Gets the text between the calling parentheses of a CallExpression or NewExpression.
|
52
|
+
* @param {ASTNode} node A CallExpression or NewExpression node.
|
53
|
+
* @returns {string} The text between the calling parentheses, or an empty string if there are none.
|
54
|
+
*/
|
55
|
+
function getArgumentsText(node) {
|
56
|
+
const lastToken = sourceCode.getLastToken(node);
|
57
|
+
|
58
|
+
if (!isClosingParenToken(lastToken)) {
|
59
|
+
return "";
|
60
|
+
}
|
61
|
+
|
62
|
+
let firstToken = node.callee;
|
63
|
+
|
64
|
+
do {
|
65
|
+
firstToken = sourceCode.getTokenAfter(firstToken);
|
66
|
+
if (!firstToken || firstToken === lastToken) {
|
67
|
+
return "";
|
68
|
+
}
|
69
|
+
} while (!isOpeningParenToken(firstToken));
|
70
|
+
|
71
|
+
return sourceCode.text.slice(firstToken.range[1], lastToken.range[0]);
|
72
|
+
}
|
73
|
+
|
32
74
|
/**
|
33
75
|
* Disallow construction of dense arrays using the Array constructor
|
34
76
|
* @param {ASTNode} node node to evaluate
|
@@ -37,11 +79,48 @@ module.exports = {
|
|
37
79
|
*/
|
38
80
|
function check(node) {
|
39
81
|
if (
|
40
|
-
node.
|
41
|
-
node.callee.
|
42
|
-
node.
|
43
|
-
|
44
|
-
|
82
|
+
node.callee.type !== "Identifier" ||
|
83
|
+
node.callee.name !== "Array" ||
|
84
|
+
node.arguments.length === 1 &&
|
85
|
+
node.arguments[0].type !== "SpreadElement") {
|
86
|
+
return;
|
87
|
+
}
|
88
|
+
|
89
|
+
const variable = getVariableByName(sourceCode.getScope(node), "Array");
|
90
|
+
|
91
|
+
/*
|
92
|
+
* Check if `Array` is a predefined global variable: predefined globals have no declarations,
|
93
|
+
* meaning that the `identifiers` list of the variable object is empty.
|
94
|
+
*/
|
95
|
+
if (variable && variable.identifiers.length === 0) {
|
96
|
+
const argsText = getArgumentsText(node);
|
97
|
+
let fixText;
|
98
|
+
let messageId;
|
99
|
+
|
100
|
+
/*
|
101
|
+
* Check if the suggested change should include a preceding semicolon or not.
|
102
|
+
* Due to JavaScript's ASI rules, a missing semicolon may be inserted automatically
|
103
|
+
* before an expression like `Array()` or `new Array()`, but not when the expression
|
104
|
+
* is changed into an array literal like `[]`.
|
105
|
+
*/
|
106
|
+
if (isStartOfExpressionStatement(node) && needsPrecedingSemicolon(sourceCode, node)) {
|
107
|
+
fixText = `;[${argsText}]`;
|
108
|
+
messageId = "useLiteralAfterSemicolon";
|
109
|
+
} else {
|
110
|
+
fixText = `[${argsText}]`;
|
111
|
+
messageId = "useLiteral";
|
112
|
+
}
|
113
|
+
|
114
|
+
context.report({
|
115
|
+
node,
|
116
|
+
messageId: "preferLiteral",
|
117
|
+
suggest: [
|
118
|
+
{
|
119
|
+
messageId,
|
120
|
+
fix: fixer => fixer.replaceText(node, fixText)
|
121
|
+
}
|
122
|
+
]
|
123
|
+
});
|
45
124
|
}
|
46
125
|
}
|
47
126
|
|
@@ -2,6 +2,7 @@
|
|
2
2
|
* @fileoverview A rule to warn against using arrow functions when they could be
|
3
3
|
* confused with comparisons
|
4
4
|
* @author Jxck <https://github.com/Jxck>
|
5
|
+
* @deprecated in ESLint v8.53.0
|
5
6
|
*/
|
6
7
|
|
7
8
|
"use strict";
|
@@ -28,6 +29,8 @@ function isConditional(node) {
|
|
28
29
|
/** @type {import('../shared/types').Rule} */
|
29
30
|
module.exports = {
|
30
31
|
meta: {
|
32
|
+
deprecated: true,
|
33
|
+
replacedBy: [],
|
31
34
|
type: "suggestion",
|
32
35
|
|
33
36
|
docs: {
|
package/lib/rules/no-console.js
CHANGED
@@ -43,8 +43,11 @@ module.exports = {
|
|
43
43
|
}
|
44
44
|
],
|
45
45
|
|
46
|
+
hasSuggestions: true,
|
47
|
+
|
46
48
|
messages: {
|
47
|
-
unexpected: "Unexpected console statement."
|
49
|
+
unexpected: "Unexpected console statement.",
|
50
|
+
removeConsole: "Remove the console.{{ propertyName }}()."
|
48
51
|
}
|
49
52
|
},
|
50
53
|
|
@@ -94,6 +97,64 @@ module.exports = {
|
|
94
97
|
);
|
95
98
|
}
|
96
99
|
|
100
|
+
/**
|
101
|
+
* Checks if removing the ExpressionStatement node will cause ASI to
|
102
|
+
* break.
|
103
|
+
* eg.
|
104
|
+
* foo()
|
105
|
+
* console.log();
|
106
|
+
* [1, 2, 3].forEach(a => doSomething(a))
|
107
|
+
*
|
108
|
+
* Removing the console.log(); statement should leave two statements, but
|
109
|
+
* here the two statements will become one because [ causes continuation after
|
110
|
+
* foo().
|
111
|
+
* @param {ASTNode} node The ExpressionStatement node to check.
|
112
|
+
* @returns {boolean} `true` if ASI will break after removing the ExpressionStatement
|
113
|
+
* node.
|
114
|
+
*/
|
115
|
+
function maybeAsiHazard(node) {
|
116
|
+
const SAFE_TOKENS_BEFORE = /^[:;{]$/u; // One of :;{
|
117
|
+
const UNSAFE_CHARS_AFTER = /^[-[(/+`]/u; // One of [(/+-`
|
118
|
+
|
119
|
+
const tokenBefore = sourceCode.getTokenBefore(node);
|
120
|
+
const tokenAfter = sourceCode.getTokenAfter(node);
|
121
|
+
|
122
|
+
return (
|
123
|
+
Boolean(tokenAfter) &&
|
124
|
+
UNSAFE_CHARS_AFTER.test(tokenAfter.value) &&
|
125
|
+
tokenAfter.value !== "++" &&
|
126
|
+
tokenAfter.value !== "--" &&
|
127
|
+
Boolean(tokenBefore) &&
|
128
|
+
!SAFE_TOKENS_BEFORE.test(tokenBefore.value)
|
129
|
+
);
|
130
|
+
}
|
131
|
+
|
132
|
+
/**
|
133
|
+
* Checks if the MemberExpression node's parent.parent.parent is a
|
134
|
+
* Program, BlockStatement, StaticBlock, or SwitchCase node. This check
|
135
|
+
* is necessary to avoid providing a suggestion that might cause a syntax error.
|
136
|
+
*
|
137
|
+
* eg. if (a) console.log(b), removing console.log() here will lead to a
|
138
|
+
* syntax error.
|
139
|
+
* if (a) { console.log(b) }, removing console.log() here is acceptable.
|
140
|
+
*
|
141
|
+
* Additionally, it checks if the callee of the CallExpression node is
|
142
|
+
* the node itself.
|
143
|
+
*
|
144
|
+
* eg. foo(console.log), cannot provide a suggestion here.
|
145
|
+
* @param {ASTNode} node The MemberExpression node to check.
|
146
|
+
* @returns {boolean} `true` if a suggestion can be provided for a node.
|
147
|
+
*/
|
148
|
+
function canProvideSuggestions(node) {
|
149
|
+
return (
|
150
|
+
node.parent.type === "CallExpression" &&
|
151
|
+
node.parent.callee === node &&
|
152
|
+
node.parent.parent.type === "ExpressionStatement" &&
|
153
|
+
astUtils.STATEMENT_LIST_PARENTS.has(node.parent.parent.parent.type) &&
|
154
|
+
!maybeAsiHazard(node.parent.parent)
|
155
|
+
);
|
156
|
+
}
|
157
|
+
|
97
158
|
/**
|
98
159
|
* Reports the given reference as a violation.
|
99
160
|
* @param {eslint-scope.Reference} reference The reference to report.
|
@@ -102,10 +163,21 @@ module.exports = {
|
|
102
163
|
function report(reference) {
|
103
164
|
const node = reference.identifier.parent;
|
104
165
|
|
166
|
+
const propertyName = astUtils.getStaticPropertyName(node);
|
167
|
+
|
105
168
|
context.report({
|
106
169
|
node,
|
107
170
|
loc: node.loc,
|
108
|
-
messageId: "unexpected"
|
171
|
+
messageId: "unexpected",
|
172
|
+
suggest: canProvideSuggestions(node)
|
173
|
+
? [{
|
174
|
+
messageId: "removeConsole",
|
175
|
+
data: { propertyName },
|
176
|
+
fix(fixer) {
|
177
|
+
return fixer.remove(node.parent.parent);
|
178
|
+
}
|
179
|
+
}]
|
180
|
+
: []
|
109
181
|
});
|
110
182
|
}
|
111
183
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* @fileoverview Disallow parenthesising higher precedence subexpressions.
|
3
3
|
* @author Michael Ficarra
|
4
|
+
* @deprecated in ESLint v8.53.0
|
4
5
|
*/
|
5
6
|
"use strict";
|
6
7
|
|
@@ -14,6 +15,8 @@ const astUtils = require("./utils/ast-utils.js");
|
|
14
15
|
/** @type {import('../shared/types').Rule} */
|
15
16
|
module.exports = {
|
16
17
|
meta: {
|
18
|
+
deprecated: true,
|
19
|
+
replacedBy: [],
|
17
20
|
type: "layout",
|
18
21
|
|
19
22
|
docs: {
|
@@ -1,6 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* @fileoverview Rule to flag use of unnecessary semicolons
|
3
3
|
* @author Nicholas C. Zakas
|
4
|
+
* @deprecated in ESLint v8.53.0
|
4
5
|
*/
|
5
6
|
|
6
7
|
"use strict";
|
@@ -19,6 +20,8 @@ const astUtils = require("./utils/ast-utils");
|
|
19
20
|
/** @type {import('../shared/types').Rule} */
|
20
21
|
module.exports = {
|
21
22
|
meta: {
|
23
|
+
deprecated: true,
|
24
|
+
replacedBy: [],
|
22
25
|
type: "suggestion",
|
23
26
|
|
24
27
|
docs: {
|
@@ -1,6 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* @fileoverview Rule to flag use of a leading/trailing decimal point in a numeric literal
|
3
3
|
* @author James Allardice
|
4
|
+
* @deprecated in ESLint v8.53.0
|
4
5
|
*/
|
5
6
|
|
6
7
|
"use strict";
|
@@ -18,6 +19,8 @@ const astUtils = require("./utils/ast-utils");
|
|
18
19
|
/** @type {import('../shared/types').Rule} */
|
19
20
|
module.exports = {
|
20
21
|
meta: {
|
22
|
+
deprecated: true,
|
23
|
+
replacedBy: [],
|
21
24
|
type: "suggestion",
|
22
25
|
|
23
26
|
docs: {
|
@@ -1,6 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* @fileoverview Rule to disallow mixed binary operators.
|
3
3
|
* @author Toru Nagashima
|
4
|
+
* @deprecated in ESLint v8.53.0
|
4
5
|
*/
|
5
6
|
|
6
7
|
"use strict";
|
@@ -85,6 +86,8 @@ function getChildNode(node) {
|
|
85
86
|
/** @type {import('../shared/types').Rule} */
|
86
87
|
module.exports = {
|
87
88
|
meta: {
|
89
|
+
deprecated: true,
|
90
|
+
replacedBy: [],
|
88
91
|
type: "suggestion",
|
89
92
|
|
90
93
|
docs: {
|
@@ -1,6 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* @fileoverview Disallow mixed spaces and tabs for indentation
|
3
3
|
* @author Jary Niebur
|
4
|
+
* @deprecated in ESLint v8.53.0
|
4
5
|
*/
|
5
6
|
"use strict";
|
6
7
|
|
@@ -11,6 +12,8 @@
|
|
11
12
|
/** @type {import('../shared/types').Rule} */
|
12
13
|
module.exports = {
|
13
14
|
meta: {
|
15
|
+
deprecated: true,
|
16
|
+
replacedBy: [],
|
14
17
|
type: "layout",
|
15
18
|
|
16
19
|
docs: {
|
@@ -1,6 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* @fileoverview Disallow use of multiple spaces.
|
3
3
|
* @author Nicholas C. Zakas
|
4
|
+
* @deprecated in ESLint v8.53.0
|
4
5
|
*/
|
5
6
|
|
6
7
|
"use strict";
|
@@ -14,6 +15,8 @@ const astUtils = require("./utils/ast-utils");
|
|
14
15
|
/** @type {import('../shared/types').Rule} */
|
15
16
|
module.exports = {
|
16
17
|
meta: {
|
18
|
+
deprecated: true,
|
19
|
+
replacedBy: [],
|
17
20
|
type: "layout",
|
18
21
|
|
19
22
|
docs: {
|
@@ -2,6 +2,7 @@
|
|
2
2
|
* @fileoverview Disallows multiple blank lines.
|
3
3
|
* implementation adapted from the no-trailing-spaces rule.
|
4
4
|
* @author Greg Cochard
|
5
|
+
* @deprecated in ESLint v8.53.0
|
5
6
|
*/
|
6
7
|
"use strict";
|
7
8
|
|
@@ -12,6 +13,8 @@
|
|
12
13
|
/** @type {import('../shared/types').Rule} */
|
13
14
|
module.exports = {
|
14
15
|
meta: {
|
16
|
+
deprecated: true,
|
17
|
+
replacedBy: [],
|
15
18
|
type: "layout",
|
16
19
|
|
17
20
|
docs: {
|
@@ -9,67 +9,12 @@
|
|
9
9
|
// Requirements
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
|
-
const {
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
const BREAK_OR_CONTINUE = new Set(["BreakStatement", "ContinueStatement"]);
|
19
|
-
|
20
|
-
// Declaration types that must contain a string Literal node at the end.
|
21
|
-
const DECLARATIONS = new Set(["ExportAllDeclaration", "ExportNamedDeclaration", "ImportDeclaration"]);
|
22
|
-
|
23
|
-
const IDENTIFIER_OR_KEYWORD = new Set(["Identifier", "Keyword"]);
|
24
|
-
|
25
|
-
// Keywords that can immediately precede an ExpressionStatement node, mapped to the their node types.
|
26
|
-
const NODE_TYPES_BY_KEYWORD = {
|
27
|
-
__proto__: null,
|
28
|
-
break: "BreakStatement",
|
29
|
-
continue: "ContinueStatement",
|
30
|
-
debugger: "DebuggerStatement",
|
31
|
-
do: "DoWhileStatement",
|
32
|
-
else: "IfStatement",
|
33
|
-
return: "ReturnStatement",
|
34
|
-
yield: "YieldExpression"
|
35
|
-
};
|
36
|
-
|
37
|
-
/*
|
38
|
-
* Before an opening parenthesis, `>` (for JSX), and postfix `++` and `--` always trigger ASI;
|
39
|
-
* the tokens `:`, `;`, `{` and `=>` don't expect a semicolon, as that would count as an empty statement.
|
40
|
-
*/
|
41
|
-
const PUNCTUATORS = new Set([":", ";", ">", "{", "=>", "++", "--"]);
|
42
|
-
|
43
|
-
/*
|
44
|
-
* Statements that can contain an `ExpressionStatement` after a closing parenthesis.
|
45
|
-
* DoWhileStatement is an exception in that it always triggers ASI after the closing parenthesis.
|
46
|
-
*/
|
47
|
-
const STATEMENTS = new Set([
|
48
|
-
"DoWhileStatement",
|
49
|
-
"ForInStatement",
|
50
|
-
"ForOfStatement",
|
51
|
-
"ForStatement",
|
52
|
-
"IfStatement",
|
53
|
-
"WhileStatement",
|
54
|
-
"WithStatement"
|
55
|
-
]);
|
56
|
-
|
57
|
-
/**
|
58
|
-
* Tests if a node appears at the beginning of an ancestor ExpressionStatement node.
|
59
|
-
* @param {ASTNode} node The node to check.
|
60
|
-
* @returns {boolean} Whether the node appears at the beginning of an ancestor ExpressionStatement node.
|
61
|
-
*/
|
62
|
-
function isStartOfExpressionStatement(node) {
|
63
|
-
const start = node.range[0];
|
64
|
-
let ancestor = node;
|
65
|
-
|
66
|
-
while ((ancestor = ancestor.parent) && ancestor.range[0] === start) {
|
67
|
-
if (ancestor.type === "ExpressionStatement") {
|
68
|
-
return true;
|
69
|
-
}
|
70
|
-
}
|
71
|
-
return false;
|
72
|
-
}
|
12
|
+
const {
|
13
|
+
getVariableByName,
|
14
|
+
isArrowToken,
|
15
|
+
isStartOfExpressionStatement,
|
16
|
+
needsPrecedingSemicolon
|
17
|
+
} = require("./utils/ast-utils");
|
73
18
|
|
74
19
|
//------------------------------------------------------------------------------
|
75
20
|
// Rule Definition
|
@@ -120,50 +65,6 @@ module.exports = {
|
|
120
65
|
return false;
|
121
66
|
}
|
122
67
|
|
123
|
-
/**
|
124
|
-
* Determines whether a parenthesized object literal that replaces a specified node needs to be preceded by a semicolon.
|
125
|
-
* @param {ASTNode} node The node to be replaced. This node should be at the start of an `ExpressionStatement` or at the start of the body of an `ArrowFunctionExpression`.
|
126
|
-
* @returns {boolean} Whether a semicolon is required before the parenthesized object literal.
|
127
|
-
*/
|
128
|
-
function needsSemicolon(node) {
|
129
|
-
const prevToken = sourceCode.getTokenBefore(node);
|
130
|
-
|
131
|
-
if (!prevToken || prevToken.type === "Punctuator" && PUNCTUATORS.has(prevToken.value)) {
|
132
|
-
return false;
|
133
|
-
}
|
134
|
-
|
135
|
-
const prevNode = sourceCode.getNodeByRangeIndex(prevToken.range[0]);
|
136
|
-
|
137
|
-
if (isClosingParenToken(prevToken)) {
|
138
|
-
return !STATEMENTS.has(prevNode.type);
|
139
|
-
}
|
140
|
-
|
141
|
-
if (isClosingBraceToken(prevToken)) {
|
142
|
-
return (
|
143
|
-
prevNode.type === "BlockStatement" && prevNode.parent.type === "FunctionExpression" ||
|
144
|
-
prevNode.type === "ClassBody" && prevNode.parent.type === "ClassExpression" ||
|
145
|
-
prevNode.type === "ObjectExpression"
|
146
|
-
);
|
147
|
-
}
|
148
|
-
|
149
|
-
if (IDENTIFIER_OR_KEYWORD.has(prevToken.type)) {
|
150
|
-
if (BREAK_OR_CONTINUE.has(prevNode.parent.type)) {
|
151
|
-
return false;
|
152
|
-
}
|
153
|
-
|
154
|
-
const keyword = prevToken.value;
|
155
|
-
const nodeType = NODE_TYPES_BY_KEYWORD[keyword];
|
156
|
-
|
157
|
-
return prevNode.type !== nodeType;
|
158
|
-
}
|
159
|
-
|
160
|
-
if (prevToken.type === "String") {
|
161
|
-
return !DECLARATIONS.has(prevNode.parent.type);
|
162
|
-
}
|
163
|
-
|
164
|
-
return true;
|
165
|
-
}
|
166
|
-
|
167
68
|
/**
|
168
69
|
* Reports on nodes where the `Object` constructor is called without arguments.
|
169
70
|
* @param {ASTNode} node The node to evaluate.
|
@@ -183,7 +84,7 @@ module.exports = {
|
|
183
84
|
|
184
85
|
if (needsParentheses(node)) {
|
185
86
|
replacement = "({})";
|
186
|
-
if (
|
87
|
+
if (needsPrecedingSemicolon(sourceCode, node)) {
|
187
88
|
fixText = ";({})";
|
188
89
|
messageId = "useLiteralAfterSemicolon";
|
189
90
|
} else {
|
@@ -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
|
}
|
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: {
|
@@ -1,6 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* @fileoverview Disallow trailing spaces at the end of lines.
|
3
3
|
* @author Nodeca Team <https://github.com/nodeca>
|
4
|
+
* @deprecated in ESLint v8.53.0
|
4
5
|
*/
|
5
6
|
"use strict";
|
6
7
|
|
@@ -17,6 +18,8 @@ const astUtils = require("./utils/ast-utils");
|
|
17
18
|
/** @type {import('../shared/types').Rule} */
|
18
19
|
module.exports = {
|
19
20
|
meta: {
|
21
|
+
deprecated: true,
|
22
|
+
replacedBy: [],
|
20
23
|
type: "layout",
|
21
24
|
|
22
25
|
docs: {
|