eslint 6.5.1 → 6.7.2
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/CHANGELOG.md +118 -0
- package/README.md +10 -9
- package/conf/config-schema.js +1 -0
- package/conf/default-cli-options.js +1 -1
- package/lib/cli-engine/cascading-config-array-factory.js +40 -14
- package/lib/cli-engine/cli-engine.js +49 -21
- package/lib/cli-engine/config-array/config-array.js +13 -4
- package/lib/cli-engine/config-array/config-dependency.js +2 -0
- package/lib/cli-engine/config-array/extracted-config.js +27 -0
- package/lib/cli-engine/config-array/ignore-pattern.js +231 -0
- package/lib/cli-engine/config-array/index.js +2 -0
- package/lib/cli-engine/config-array/override-tester.js +2 -0
- package/lib/cli-engine/config-array-factory.js +120 -2
- package/lib/cli-engine/file-enumerator.js +65 -34
- package/lib/cli-engine/formatters/html.js +1 -0
- package/lib/init/autoconfig.js +1 -11
- package/lib/init/config-file.js +0 -1
- package/lib/init/config-initializer.js +4 -4
- package/lib/init/config-rule.js +1 -5
- package/lib/init/npm-utils.js +0 -5
- package/lib/linter/code-path-analysis/code-path-analyzer.js +24 -38
- package/lib/linter/code-path-analysis/code-path-segment.js +17 -25
- package/lib/linter/code-path-analysis/code-path-state.js +40 -81
- package/lib/linter/code-path-analysis/code-path.js +10 -11
- package/lib/linter/code-path-analysis/debug-helpers.js +8 -12
- package/lib/linter/code-path-analysis/fork-context.js +23 -34
- package/lib/linter/code-path-analysis/id-generator.js +2 -2
- package/lib/linter/linter.js +121 -95
- package/lib/linter/node-event-generator.js +3 -2
- package/lib/linter/report-translator.js +73 -7
- package/lib/rule-tester/rule-tester.js +46 -14
- package/lib/rules/accessor-pairs.js +8 -8
- package/lib/rules/array-bracket-newline.js +12 -15
- package/lib/rules/array-bracket-spacing.js +12 -12
- package/lib/rules/array-callback-return.js +6 -11
- package/lib/rules/array-element-newline.js +5 -8
- package/lib/rules/arrow-parens.js +0 -1
- package/lib/rules/block-scoped-var.js +3 -3
- package/lib/rules/block-spacing.js +4 -4
- package/lib/rules/camelcase.js +19 -6
- package/lib/rules/capitalized-comments.js +0 -7
- package/lib/rules/class-methods-use-this.js +3 -3
- package/lib/rules/comma-dangle.js +20 -25
- package/lib/rules/comma-spacing.js +1 -1
- package/lib/rules/computed-property-spacing.js +14 -14
- package/lib/rules/consistent-return.js +4 -5
- package/lib/rules/consistent-this.js +5 -5
- package/lib/rules/constructor-super.js +14 -16
- package/lib/rules/curly.js +12 -9
- package/lib/rules/default-param-last.js +1 -0
- package/lib/rules/dot-location.js +11 -12
- package/lib/rules/func-names.js +6 -6
- package/lib/rules/function-call-argument-newline.js +8 -6
- package/lib/rules/generator-star-spacing.js +4 -9
- package/lib/rules/getter-return.js +4 -7
- package/lib/rules/grouped-accessor-pairs.js +224 -0
- package/lib/rules/indent.js +13 -2
- package/lib/rules/index.js +5 -0
- package/lib/rules/init-declarations.js +2 -2
- package/lib/rules/jsx-quotes.js +1 -1
- package/lib/rules/keyword-spacing.js +32 -56
- package/lib/rules/lines-around-directive.js +1 -1
- package/lib/rules/max-len.js +0 -5
- package/lib/rules/max-statements-per-line.js +3 -7
- package/lib/rules/multiline-comment-style.js +237 -106
- package/lib/rules/multiline-ternary.js +3 -3
- package/lib/rules/newline-after-var.js +6 -7
- package/lib/rules/newline-before-return.js +8 -9
- package/lib/rules/newline-per-chained-call.js +2 -4
- package/lib/rules/no-class-assign.js +2 -2
- package/lib/rules/no-compare-neg-zero.js +1 -2
- package/lib/rules/no-cond-assign.js +14 -4
- package/lib/rules/no-confusing-arrow.js +2 -2
- package/lib/rules/no-console.js +4 -8
- package/lib/rules/no-const-assign.js +1 -1
- package/lib/rules/no-constructor-return.js +62 -0
- package/lib/rules/no-dupe-args.js +1 -1
- package/lib/rules/no-dupe-class-members.js +3 -4
- package/lib/rules/no-dupe-else-if.js +122 -0
- package/lib/rules/no-dupe-keys.js +6 -5
- package/lib/rules/no-duplicate-imports.js +14 -18
- package/lib/rules/no-else-return.js +0 -8
- package/lib/rules/no-empty-function.js +2 -4
- package/lib/rules/no-eval.js +10 -18
- package/lib/rules/no-ex-assign.js +1 -1
- package/lib/rules/no-extra-bind.js +5 -12
- package/lib/rules/no-extra-boolean-cast.js +0 -2
- package/lib/rules/no-extra-label.js +4 -9
- package/lib/rules/no-extra-parens.js +17 -15
- package/lib/rules/no-extra-semi.js +5 -6
- package/lib/rules/no-fallthrough.js +6 -6
- package/lib/rules/no-func-assign.js +3 -3
- package/lib/rules/no-global-assign.js +4 -4
- package/lib/rules/no-implicit-coercion.js +10 -10
- package/lib/rules/no-implicit-globals.js +90 -8
- package/lib/rules/no-implied-eval.js +0 -1
- package/lib/rules/no-inline-comments.js +25 -11
- package/lib/rules/no-invalid-this.js +17 -5
- package/lib/rules/no-labels.js +3 -6
- package/lib/rules/no-lone-blocks.js +1 -1
- package/lib/rules/no-loop-func.js +6 -11
- package/lib/rules/no-magic-numbers.js +6 -6
- package/lib/rules/no-misleading-character-class.js +14 -7
- package/lib/rules/no-mixed-operators.js +13 -22
- package/lib/rules/no-mixed-requires.js +0 -1
- package/lib/rules/no-multi-spaces.js +1 -1
- package/lib/rules/no-native-reassign.js +4 -4
- package/lib/rules/no-octal-escape.js +1 -1
- package/lib/rules/no-param-reassign.js +28 -7
- package/lib/rules/no-redeclare.js +1 -1
- package/lib/rules/no-regex-spaces.js +0 -1
- package/lib/rules/no-restricted-imports.js +11 -11
- package/lib/rules/no-self-assign.js +12 -13
- package/lib/rules/no-sequences.js +3 -3
- package/lib/rules/no-setter-return.js +227 -0
- package/lib/rules/no-shadow.js +1 -4
- package/lib/rules/no-tabs.js +8 -2
- package/lib/rules/no-this-before-super.js +12 -13
- package/lib/rules/no-trailing-spaces.js +19 -7
- package/lib/rules/no-underscore-dangle.js +23 -4
- package/lib/rules/no-unexpected-multiline.js +8 -0
- package/lib/rules/no-unmodified-loop-condition.js +16 -29
- package/lib/rules/no-unneeded-ternary.js +3 -3
- package/lib/rules/no-unreachable.js +7 -7
- package/lib/rules/no-unsafe-finally.js +4 -7
- package/lib/rules/no-unsafe-negation.js +32 -9
- package/lib/rules/no-unused-expressions.js +11 -7
- package/lib/rules/no-unused-labels.js +3 -6
- package/lib/rules/no-unused-vars.js +22 -29
- package/lib/rules/no-use-before-define.js +10 -15
- package/lib/rules/no-useless-call.js +4 -4
- package/lib/rules/no-useless-computed-key.js +60 -33
- package/lib/rules/no-useless-concat.js +4 -4
- package/lib/rules/no-useless-constructor.js +14 -22
- package/lib/rules/no-useless-escape.js +29 -8
- package/lib/rules/no-useless-rename.js +7 -7
- package/lib/rules/no-useless-return.js +8 -15
- package/lib/rules/no-var.js +12 -25
- package/lib/rules/no-warning-comments.js +0 -1
- package/lib/rules/no-whitespace-before-property.js +3 -3
- package/lib/rules/object-curly-newline.js +7 -10
- package/lib/rules/object-curly-spacing.js +21 -22
- package/lib/rules/object-shorthand.js +1 -1
- package/lib/rules/one-var-declaration-per-line.js +2 -2
- package/lib/rules/operator-assignment.js +33 -3
- package/lib/rules/padded-blocks.js +1 -1
- package/lib/rules/padding-line-between-statements.js +0 -16
- package/lib/rules/prefer-arrow-callback.js +6 -6
- package/lib/rules/prefer-const.js +27 -28
- package/lib/rules/prefer-destructuring.js +1 -7
- package/lib/rules/prefer-exponentiation-operator.js +189 -0
- package/lib/rules/prefer-named-capture-group.js +0 -1
- package/lib/rules/prefer-numeric-literals.js +32 -4
- package/lib/rules/prefer-object-spread.js +7 -7
- package/lib/rules/prefer-rest-params.js +3 -6
- package/lib/rules/prefer-spread.js +4 -4
- package/lib/rules/prefer-template.js +5 -6
- package/lib/rules/quote-props.js +1 -1
- package/lib/rules/quotes.js +5 -6
- package/lib/rules/radix.js +5 -10
- package/lib/rules/require-await.js +10 -5
- package/lib/rules/require-yield.js +2 -2
- package/lib/rules/rest-spread-spacing.js +1 -1
- package/lib/rules/semi.js +6 -3
- package/lib/rules/sort-imports.js +3 -4
- package/lib/rules/sort-keys.js +1 -3
- package/lib/rules/space-before-blocks.js +1 -2
- package/lib/rules/space-in-parens.js +4 -4
- package/lib/rules/space-infix-ops.js +6 -6
- package/lib/rules/spaced-comment.js +20 -22
- package/lib/rules/strict.js +2 -4
- package/lib/rules/symbol-description.js +1 -2
- package/lib/rules/template-curly-spacing.js +2 -2
- package/lib/rules/use-isnan.js +40 -3
- package/lib/rules/utils/ast-utils.js +84 -85
- package/lib/rules/utils/fix-tracker.js +0 -6
- package/lib/rules/utils/lazy-loading-rule-map.js +0 -1
- package/lib/rules/vars-on-top.js +11 -11
- package/lib/shared/config-ops.js +2 -2
- package/lib/shared/runtime-info.js +8 -8
- package/lib/shared/traverser.js +2 -0
- package/lib/shared/types.js +9 -0
- package/lib/source-code/source-code.js +94 -17
- package/lib/source-code/token-store/backward-token-comment-cursor.js +5 -5
- package/lib/source-code/token-store/backward-token-cursor.js +5 -5
- package/lib/source-code/token-store/cursors.js +17 -19
- package/lib/source-code/token-store/decorative-cursor.js +1 -1
- package/lib/source-code/token-store/filter-cursor.js +2 -2
- package/lib/source-code/token-store/forward-token-comment-cursor.js +5 -5
- package/lib/source-code/token-store/forward-token-cursor.js +5 -5
- package/lib/source-code/token-store/index.js +86 -92
- package/lib/source-code/token-store/limit-cursor.js +2 -2
- package/lib/source-code/token-store/padded-token-cursor.js +7 -7
- package/lib/source-code/token-store/skip-cursor.js +2 -2
- package/lib/source-code/token-store/utils.js +9 -13
- package/package.json +9 -7
- package/lib/cli-engine/ignored-paths.js +0 -362
@@ -71,6 +71,9 @@ function same(a, b) {
|
|
71
71
|
*/
|
72
72
|
return same(a.object, b.object) && same(a.property, b.property);
|
73
73
|
|
74
|
+
case "ThisExpression":
|
75
|
+
return true;
|
76
|
+
|
74
77
|
default:
|
75
78
|
return false;
|
76
79
|
}
|
@@ -83,8 +86,14 @@ function same(a, b) {
|
|
83
86
|
* @returns {boolean} `true` if the node can be fixed
|
84
87
|
*/
|
85
88
|
function canBeFixed(node) {
|
86
|
-
return
|
87
|
-
node.type === "
|
89
|
+
return (
|
90
|
+
node.type === "Identifier" ||
|
91
|
+
(
|
92
|
+
node.type === "MemberExpression" &&
|
93
|
+
(node.object.type === "Identifier" || node.object.type === "ThisExpression") &&
|
94
|
+
(!node.computed || node.property.type === "Literal")
|
95
|
+
)
|
96
|
+
);
|
88
97
|
}
|
89
98
|
|
90
99
|
module.exports = {
|
@@ -150,6 +159,11 @@ module.exports = {
|
|
150
159
|
const leftText = sourceCode.getText().slice(node.range[0], equalsToken.range[0]);
|
151
160
|
const rightText = sourceCode.getText().slice(operatorToken.range[1], node.right.range[1]);
|
152
161
|
|
162
|
+
// Check for comments that would be removed.
|
163
|
+
if (sourceCode.commentsExistBetween(equalsToken, operatorToken)) {
|
164
|
+
return null;
|
165
|
+
}
|
166
|
+
|
153
167
|
return fixer.replaceText(node, `${leftText}${expr.operator}=${rightText}`);
|
154
168
|
}
|
155
169
|
return null;
|
@@ -182,11 +196,17 @@ module.exports = {
|
|
182
196
|
messageId: "unexpected",
|
183
197
|
fix(fixer) {
|
184
198
|
if (canBeFixed(node.left)) {
|
199
|
+
const firstToken = sourceCode.getFirstToken(node);
|
185
200
|
const operatorToken = getOperatorToken(node);
|
186
201
|
const leftText = sourceCode.getText().slice(node.range[0], operatorToken.range[0]);
|
187
202
|
const newOperator = node.operator.slice(0, -1);
|
188
203
|
let rightText;
|
189
204
|
|
205
|
+
// Check for comments that would be duplicated.
|
206
|
+
if (sourceCode.commentsExistBetween(firstToken, operatorToken)) {
|
207
|
+
return null;
|
208
|
+
}
|
209
|
+
|
190
210
|
// If this change would modify precedence (e.g. `foo *= bar + 1` => `foo = foo * (bar + 1)`), parenthesize the right side.
|
191
211
|
if (
|
192
212
|
astUtils.getPrecedence(node.right) <= astUtils.getPrecedence({ type: "BinaryExpression", operator: newOperator }) &&
|
@@ -194,7 +214,17 @@ module.exports = {
|
|
194
214
|
) {
|
195
215
|
rightText = `${sourceCode.text.slice(operatorToken.range[1], node.right.range[0])}(${sourceCode.getText(node.right)})`;
|
196
216
|
} else {
|
197
|
-
|
217
|
+
const firstRightToken = sourceCode.getFirstToken(node.right);
|
218
|
+
let rightTextPrefix = "";
|
219
|
+
|
220
|
+
if (
|
221
|
+
operatorToken.range[1] === firstRightToken.range[0] &&
|
222
|
+
!astUtils.canTokensBeAdjacent(newOperator, firstRightToken)
|
223
|
+
) {
|
224
|
+
rightTextPrefix = " "; // foo+=+bar -> foo= foo+ +bar
|
225
|
+
}
|
226
|
+
|
227
|
+
rightText = `${rightTextPrefix}${sourceCode.text.slice(operatorToken.range[1], node.range[1])}`;
|
198
228
|
}
|
199
229
|
|
200
230
|
return fixer.replaceText(node, `${leftText}= ${leftText}${newOperator}${rightText}`);
|
@@ -97,7 +97,7 @@ module.exports = {
|
|
97
97
|
|
98
98
|
/**
|
99
99
|
* Gets the open brace token from a given node.
|
100
|
-
* @param {ASTNode} node
|
100
|
+
* @param {ASTNode} node A BlockStatement or SwitchStatement node from which to get the open brace.
|
101
101
|
* @returns {Token} The token of the open brace.
|
102
102
|
*/
|
103
103
|
function getOpenBrace(node) {
|
@@ -25,7 +25,6 @@ const CJS_IMPORT = /^require\(/u;
|
|
25
25
|
|
26
26
|
/**
|
27
27
|
* Creates tester which check if a node starts with specific keyword.
|
28
|
-
*
|
29
28
|
* @param {string} keyword The keyword to test.
|
30
29
|
* @returns {Object} the created tester.
|
31
30
|
* @private
|
@@ -39,7 +38,6 @@ function newKeywordTester(keyword) {
|
|
39
38
|
|
40
39
|
/**
|
41
40
|
* Creates tester which check if a node starts with specific keyword and spans a single line.
|
42
|
-
*
|
43
41
|
* @param {string} keyword The keyword to test.
|
44
42
|
* @returns {Object} the created tester.
|
45
43
|
* @private
|
@@ -54,7 +52,6 @@ function newSinglelineKeywordTester(keyword) {
|
|
54
52
|
|
55
53
|
/**
|
56
54
|
* Creates tester which check if a node starts with specific keyword and spans multiple lines.
|
57
|
-
*
|
58
55
|
* @param {string} keyword The keyword to test.
|
59
56
|
* @returns {Object} the created tester.
|
60
57
|
* @private
|
@@ -69,7 +66,6 @@ function newMultilineKeywordTester(keyword) {
|
|
69
66
|
|
70
67
|
/**
|
71
68
|
* Creates tester which check if a node is specific type.
|
72
|
-
*
|
73
69
|
* @param {string} type The node type to test.
|
74
70
|
* @returns {Object} the created tester.
|
75
71
|
* @private
|
@@ -83,7 +79,6 @@ function newNodeTypeTester(type) {
|
|
83
79
|
|
84
80
|
/**
|
85
81
|
* Checks the given node is an expression statement of IIFE.
|
86
|
-
*
|
87
82
|
* @param {ASTNode} node The node to check.
|
88
83
|
* @returns {boolean} `true` if the node is an expression statement of IIFE.
|
89
84
|
* @private
|
@@ -103,7 +98,6 @@ function isIIFEStatement(node) {
|
|
103
98
|
/**
|
104
99
|
* Checks whether the given node is a block-like statement.
|
105
100
|
* This checks the last token of the node is the closing brace of a block.
|
106
|
-
*
|
107
101
|
* @param {SourceCode} sourceCode The source code to get tokens.
|
108
102
|
* @param {ASTNode} node The node to check.
|
109
103
|
* @returns {boolean} `true` if the node is a block-like statement.
|
@@ -187,7 +181,6 @@ function isDirectivePrologue(node, sourceCode) {
|
|
187
181
|
*
|
188
182
|
* foo()
|
189
183
|
* ;[1, 2, 3].forEach(bar)
|
190
|
-
*
|
191
184
|
* @param {SourceCode} sourceCode The source code to get tokens.
|
192
185
|
* @param {ASTNode} node The node to get.
|
193
186
|
* @returns {Token} The actual last token.
|
@@ -224,7 +217,6 @@ function replacerToRemovePaddingLines(_, trailingSpaces, indentSpaces) {
|
|
224
217
|
/**
|
225
218
|
* Check and report statements for `any` configuration.
|
226
219
|
* It does nothing.
|
227
|
-
*
|
228
220
|
* @returns {void}
|
229
221
|
* @private
|
230
222
|
*/
|
@@ -236,7 +228,6 @@ function verifyForAny() {
|
|
236
228
|
* This autofix removes blank lines between the given 2 statements.
|
237
229
|
* However, if comments exist between 2 blank lines, it does not remove those
|
238
230
|
* blank lines automatically.
|
239
|
-
*
|
240
231
|
* @param {RuleContext} context The rule context to report.
|
241
232
|
* @param {ASTNode} _ Unused. The previous node to check.
|
242
233
|
* @param {ASTNode} nextNode The next node to check.
|
@@ -276,7 +267,6 @@ function verifyForNever(context, _, nextNode, paddingLines) {
|
|
276
267
|
* This autofix inserts a blank line between the given 2 statements.
|
277
268
|
* If the `prevNode` has trailing comments, it inserts a blank line after the
|
278
269
|
* trailing comments.
|
279
|
-
*
|
280
270
|
* @param {RuleContext} context The rule context to report.
|
281
271
|
* @param {ASTNode} prevNode The previous node to check.
|
282
272
|
* @param {ASTNode} nextNode The next node to check.
|
@@ -318,7 +308,6 @@ function verifyForAlways(context, prevNode, nextNode, paddingLines) {
|
|
318
308
|
*
|
319
309
|
* // comment.
|
320
310
|
* bar();
|
321
|
-
*
|
322
311
|
* @param {Token} token The token to check.
|
323
312
|
* @returns {boolean} `true` if the token is not a trailing comment.
|
324
313
|
* @private
|
@@ -511,7 +500,6 @@ module.exports = {
|
|
511
500
|
|
512
501
|
/**
|
513
502
|
* Checks whether the given node matches the given type.
|
514
|
-
*
|
515
503
|
* @param {ASTNode} node The statement node to check.
|
516
504
|
* @param {string|string[]} type The statement type to check.
|
517
505
|
* @returns {boolean} `true` if the statement node matched the type.
|
@@ -531,7 +519,6 @@ module.exports = {
|
|
531
519
|
|
532
520
|
/**
|
533
521
|
* Finds the last matched configure from configureList.
|
534
|
-
*
|
535
522
|
* @param {ASTNode} prevNode The previous statement to match.
|
536
523
|
* @param {ASTNode} nextNode The current statement to match.
|
537
524
|
* @returns {Object} The tester of the last matched configure.
|
@@ -554,7 +541,6 @@ module.exports = {
|
|
554
541
|
/**
|
555
542
|
* Gets padding line sequences between the given 2 statements.
|
556
543
|
* Comments are separators of the padding line sequences.
|
557
|
-
*
|
558
544
|
* @param {ASTNode} prevNode The previous statement to count.
|
559
545
|
* @param {ASTNode} nextNode The current statement to count.
|
560
546
|
* @returns {Array<Token[]>} The array of token pairs.
|
@@ -584,7 +570,6 @@ module.exports = {
|
|
584
570
|
|
585
571
|
/**
|
586
572
|
* Verify padding lines between the given node and the previous node.
|
587
|
-
*
|
588
573
|
* @param {ASTNode} node The node to verify.
|
589
574
|
* @returns {void}
|
590
575
|
* @private
|
@@ -616,7 +601,6 @@ module.exports = {
|
|
616
601
|
/**
|
617
602
|
* Verify padding lines between the given node and the previous node.
|
618
603
|
* Then process to enter to new scope.
|
619
|
-
*
|
620
604
|
* @param {ASTNode} node The node to verify.
|
621
605
|
* @returns {void}
|
622
606
|
* @private
|
@@ -11,7 +11,7 @@
|
|
11
11
|
|
12
12
|
/**
|
13
13
|
* Checks whether or not a given variable is a function name.
|
14
|
-
* @param {eslint-scope.Variable} variable
|
14
|
+
* @param {eslint-scope.Variable} variable A variable to check.
|
15
15
|
* @returns {boolean} `true` if the variable is a function name.
|
16
16
|
*/
|
17
17
|
function isFunctionName(variable) {
|
@@ -20,9 +20,9 @@ function isFunctionName(variable) {
|
|
20
20
|
|
21
21
|
/**
|
22
22
|
* Checks whether or not a given MetaProperty node equals to a given value.
|
23
|
-
* @param {ASTNode} node
|
24
|
-
* @param {string} metaName
|
25
|
-
* @param {string} propertyName
|
23
|
+
* @param {ASTNode} node A MetaProperty node to check.
|
24
|
+
* @param {string} metaName The name of `MetaProperty.meta`.
|
25
|
+
* @param {string} propertyName The name of `MetaProperty.property`.
|
26
26
|
* @returns {boolean} `true` if the node is the specific value.
|
27
27
|
*/
|
28
28
|
function checkMetaProperty(node, metaName, propertyName) {
|
@@ -31,7 +31,7 @@ function checkMetaProperty(node, metaName, propertyName) {
|
|
31
31
|
|
32
32
|
/**
|
33
33
|
* Gets the variable object of `arguments` which is defined implicitly.
|
34
|
-
* @param {eslint-scope.Scope} scope
|
34
|
+
* @param {eslint-scope.Scope} scope A scope to get.
|
35
35
|
* @returns {eslint-scope.Variable} The found variable object.
|
36
36
|
*/
|
37
37
|
function getVariableOfArguments(scope) {
|
@@ -57,7 +57,7 @@ function getVariableOfArguments(scope) {
|
|
57
57
|
|
58
58
|
/**
|
59
59
|
* Checkes whether or not a given node is a callback.
|
60
|
-
* @param {ASTNode} node
|
60
|
+
* @param {ASTNode} node A node to check.
|
61
61
|
* @returns {Object}
|
62
62
|
* {boolean} retv.isCallback - `true` if the node is a callback.
|
63
63
|
* {boolean} retv.isLexicalThis - `true` if the node is with `.bind(this)`.
|
@@ -17,8 +17,7 @@ const DESTRUCTURING_HOST_TYPE = /^(?:VariableDeclarator|AssignmentExpression)$/u
|
|
17
17
|
|
18
18
|
/**
|
19
19
|
* Checks whether a given node is located at `ForStatement.init` or not.
|
20
|
-
*
|
21
|
-
* @param {ASTNode} node - A node to check.
|
20
|
+
* @param {ASTNode} node A node to check.
|
22
21
|
* @returns {boolean} `true` if the node is located at `ForStatement.init`.
|
23
22
|
*/
|
24
23
|
function isInitOfForStatement(node) {
|
@@ -27,8 +26,7 @@ function isInitOfForStatement(node) {
|
|
27
26
|
|
28
27
|
/**
|
29
28
|
* Checks whether a given Identifier node becomes a VariableDeclaration or not.
|
30
|
-
*
|
31
|
-
* @param {ASTNode} identifier - An Identifier node to check.
|
29
|
+
* @param {ASTNode} identifier An Identifier node to check.
|
32
30
|
* @returns {boolean} `true` if the node can become a VariableDeclaration.
|
33
31
|
*/
|
34
32
|
function canBecomeVariableDeclaration(identifier) {
|
@@ -51,9 +49,8 @@ function canBecomeVariableDeclaration(identifier) {
|
|
51
49
|
/**
|
52
50
|
* Checks if an property or element is from outer scope or function parameters
|
53
51
|
* in destructing pattern.
|
54
|
-
*
|
55
|
-
* @param {
|
56
|
-
* @param {eslint-scope.Scope} initScope - A scope to start find.
|
52
|
+
* @param {string} name A variable name to be checked.
|
53
|
+
* @param {eslint-scope.Scope} initScope A scope to start find.
|
57
54
|
* @returns {boolean} Indicates if the variable is from outer scope or function parameters.
|
58
55
|
*/
|
59
56
|
function isOuterVariableInDestructing(name, initScope) {
|
@@ -76,8 +73,7 @@ function isOuterVariableInDestructing(name, initScope) {
|
|
76
73
|
* belongs to.
|
77
74
|
* This is used to detect a mix of reassigned and never reassigned in a
|
78
75
|
* destructuring.
|
79
|
-
*
|
80
|
-
* @param {eslint-scope.Reference} reference - A reference to get.
|
76
|
+
* @param {eslint-scope.Reference} reference A reference to get.
|
81
77
|
* @returns {ASTNode|null} A VariableDeclarator/AssignmentExpression node or
|
82
78
|
* null.
|
83
79
|
*/
|
@@ -162,9 +158,8 @@ function hasMemberExpressionAssignment(node) {
|
|
162
158
|
* `/*exported foo` directive comment makes such variables. This rule does not
|
163
159
|
* warn such variables because this rule cannot distinguish whether the
|
164
160
|
* exported variables are reassigned or not.
|
165
|
-
*
|
166
|
-
* @param {
|
167
|
-
* @param {boolean} ignoreReadBeforeAssign -
|
161
|
+
* @param {eslint-scope.Variable} variable A variable to get.
|
162
|
+
* @param {boolean} ignoreReadBeforeAssign
|
168
163
|
* The value of `ignoreReadBeforeAssign` option.
|
169
164
|
* @returns {ASTNode|null}
|
170
165
|
* An Identifier node if the variable should change to const.
|
@@ -262,9 +257,8 @@ function getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign) {
|
|
262
257
|
* reference of given variables belongs to.
|
263
258
|
* This is used to detect a mix of reassigned and never reassigned in a
|
264
259
|
* destructuring.
|
265
|
-
*
|
266
|
-
* @param {
|
267
|
-
* @param {boolean} ignoreReadBeforeAssign -
|
260
|
+
* @param {eslint-scope.Variable[]} variables Variables to group by destructuring.
|
261
|
+
* @param {boolean} ignoreReadBeforeAssign
|
268
262
|
* The value of `ignoreReadBeforeAssign` option.
|
269
263
|
* @returns {Map<ASTNode, ASTNode[]>} Grouped identifier nodes.
|
270
264
|
*/
|
@@ -308,10 +302,9 @@ function groupByDestructuring(variables, ignoreReadBeforeAssign) {
|
|
308
302
|
|
309
303
|
/**
|
310
304
|
* Finds the nearest parent of node with a given type.
|
311
|
-
*
|
312
|
-
* @param {
|
313
|
-
* @param {
|
314
|
-
* @param {Function} shouldStop – a predicate that returns true if the traversal should stop, and false otherwise.
|
305
|
+
* @param {ASTNode} node The node to search from.
|
306
|
+
* @param {string} type The type field of the parent node.
|
307
|
+
* @param {Function} shouldStop A predicate that returns true if the traversal should stop, and false otherwise.
|
315
308
|
* @returns {ASTNode} The closest ancestor with the specified type; null if no such ancestor exists.
|
316
309
|
*/
|
317
310
|
function findUp(node, type, shouldStop) {
|
@@ -363,7 +356,9 @@ module.exports = {
|
|
363
356
|
const ignoreReadBeforeAssign = options.ignoreReadBeforeAssign === true;
|
364
357
|
const variables = [];
|
365
358
|
let reportCount = 0;
|
366
|
-
let
|
359
|
+
let checkedId = null;
|
360
|
+
let checkedName = "";
|
361
|
+
|
367
362
|
|
368
363
|
/**
|
369
364
|
* Reports given identifier nodes if all of the nodes should be declared
|
@@ -374,8 +369,7 @@ module.exports = {
|
|
374
369
|
* nullable. In simple declaration or assignment cases, the length of
|
375
370
|
* the array is 1. In destructuring cases, the length of the array can
|
376
371
|
* be 2 or more.
|
377
|
-
*
|
378
|
-
* @param {(eslint-scope.Reference|null)[]} nodes -
|
372
|
+
* @param {(eslint-scope.Reference|null)[]} nodes
|
379
373
|
* References which are grouped by destructuring to report.
|
380
374
|
* @returns {void}
|
381
375
|
*/
|
@@ -395,25 +389,30 @@ module.exports = {
|
|
395
389
|
/*
|
396
390
|
* First we check the declaration type and then depending on
|
397
391
|
* if the type is a "VariableDeclarator" or its an "ObjectPattern"
|
398
|
-
* we compare the name from the first identifier, if the names are different
|
399
|
-
* we assign the new name and reset the count of reportCount and nodeCount in
|
392
|
+
* we compare the name and id from the first identifier, if the names are different
|
393
|
+
* we assign the new name, id and reset the count of reportCount and nodeCount in
|
400
394
|
* order to check each block for the number of reported errors and base our fix
|
401
395
|
* based on comparing nodes.length and nodesToReport.length.
|
402
396
|
*/
|
403
397
|
|
404
398
|
if (firstDecParent.type === "VariableDeclarator") {
|
405
399
|
|
406
|
-
if (firstDecParent.id.name !==
|
407
|
-
|
400
|
+
if (firstDecParent.id.name !== checkedName) {
|
401
|
+
checkedName = firstDecParent.id.name;
|
408
402
|
reportCount = 0;
|
409
403
|
}
|
410
404
|
|
411
405
|
if (firstDecParent.id.type === "ObjectPattern") {
|
412
|
-
if (firstDecParent.init.name !==
|
413
|
-
|
406
|
+
if (firstDecParent.init.name !== checkedName) {
|
407
|
+
checkedName = firstDecParent.init.name;
|
414
408
|
reportCount = 0;
|
415
409
|
}
|
416
410
|
}
|
411
|
+
|
412
|
+
if (firstDecParent.id !== checkedId) {
|
413
|
+
checkedId = firstDecParent.id;
|
414
|
+
reportCount = 0;
|
415
|
+
}
|
417
416
|
}
|
418
417
|
}
|
419
418
|
}
|
@@ -103,6 +103,7 @@ module.exports = {
|
|
103
103
|
// Helpers
|
104
104
|
//--------------------------------------------------------------------------
|
105
105
|
|
106
|
+
// eslint-disable-next-line jsdoc/require-description
|
106
107
|
/**
|
107
108
|
* @param {string} nodeType "AssignmentExpression" or "VariableDeclarator"
|
108
109
|
* @param {string} destructuringType "array" or "object"
|
@@ -119,7 +120,6 @@ module.exports = {
|
|
119
120
|
*
|
120
121
|
* This is used to differentiate array index access from object property
|
121
122
|
* access.
|
122
|
-
*
|
123
123
|
* @param {ASTNode} node the node to evaluate
|
124
124
|
* @returns {boolean} whether or not the node is an integer
|
125
125
|
*/
|
@@ -129,7 +129,6 @@ module.exports = {
|
|
129
129
|
|
130
130
|
/**
|
131
131
|
* Report that the given node should use destructuring
|
132
|
-
*
|
133
132
|
* @param {ASTNode} reportNode the node to report
|
134
133
|
* @param {string} type the type of destructuring that should have been done
|
135
134
|
* @param {Function|null} fix the fix function or null to pass to context.report
|
@@ -153,7 +152,6 @@ module.exports = {
|
|
153
152
|
* Assignment expression is not fixed.
|
154
153
|
* Array destructuring is not fixed.
|
155
154
|
* Renamed property is not fixed.
|
156
|
-
*
|
157
155
|
* @param {ASTNode} node the the node to evaluate
|
158
156
|
* @returns {boolean} whether or not the node should be fixed
|
159
157
|
*/
|
@@ -168,7 +166,6 @@ module.exports = {
|
|
168
166
|
* Fix a node into object destructuring.
|
169
167
|
* This function only handles the simplest case of object destructuring,
|
170
168
|
* see {@link shouldFix}.
|
171
|
-
*
|
172
169
|
* @param {SourceCodeFixer} fixer the fixer object
|
173
170
|
* @param {ASTNode} node the node to be fixed.
|
174
171
|
* @returns {Object} a fix for the node
|
@@ -189,7 +186,6 @@ module.exports = {
|
|
189
186
|
*
|
190
187
|
* Pulled out into a separate method so that VariableDeclarators and
|
191
188
|
* AssignmentExpressions can share the same verification logic.
|
192
|
-
*
|
193
189
|
* @param {ASTNode} leftNode the left-hand side of the assignment
|
194
190
|
* @param {ASTNode} rightNode the right-hand side of the assignment
|
195
191
|
* @param {ASTNode} reportNode the node to report the error on
|
@@ -231,7 +227,6 @@ module.exports = {
|
|
231
227
|
/**
|
232
228
|
* Check if a given variable declarator is coming from an property access
|
233
229
|
* that should be using destructuring instead
|
234
|
-
*
|
235
230
|
* @param {ASTNode} node the variable declarator to check
|
236
231
|
* @returns {void}
|
237
232
|
*/
|
@@ -252,7 +247,6 @@ module.exports = {
|
|
252
247
|
|
253
248
|
/**
|
254
249
|
* Run the `prefer-destructuring` check on an AssignmentExpression
|
255
|
-
*
|
256
250
|
* @param {ASTNode} node the AssignmentExpression node
|
257
251
|
* @returns {void}
|
258
252
|
*/
|
@@ -0,0 +1,189 @@
|
|
1
|
+
/**
|
2
|
+
* @fileoverview Rule to disallow Math.pow in favor of the ** operator
|
3
|
+
* @author Milos Djermanovic
|
4
|
+
*/
|
5
|
+
|
6
|
+
"use strict";
|
7
|
+
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Requirements
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
const astUtils = require("./utils/ast-utils");
|
13
|
+
const { CALL, ReferenceTracker } = require("eslint-utils");
|
14
|
+
|
15
|
+
//------------------------------------------------------------------------------
|
16
|
+
// Helpers
|
17
|
+
//------------------------------------------------------------------------------
|
18
|
+
|
19
|
+
const PRECEDENCE_OF_EXPONENTIATION_EXPR = astUtils.getPrecedence({ type: "BinaryExpression", operator: "**" });
|
20
|
+
|
21
|
+
/**
|
22
|
+
* Determines whether the given node needs parens if used as the base in an exponentiation binary expression.
|
23
|
+
* @param {ASTNode} base The node to check.
|
24
|
+
* @returns {boolean} `true` if the node needs to be parenthesised.
|
25
|
+
*/
|
26
|
+
function doesBaseNeedParens(base) {
|
27
|
+
return (
|
28
|
+
|
29
|
+
// '**' is right-associative, parens are needed when Math.pow(a ** b, c) is converted to (a ** b) ** c
|
30
|
+
astUtils.getPrecedence(base) <= PRECEDENCE_OF_EXPONENTIATION_EXPR ||
|
31
|
+
|
32
|
+
// An unary operator cannot be used immediately before an exponentiation expression
|
33
|
+
base.type === "UnaryExpression"
|
34
|
+
);
|
35
|
+
}
|
36
|
+
|
37
|
+
/**
|
38
|
+
* Determines whether the given node needs parens if used as the exponent in an exponentiation binary expression.
|
39
|
+
* @param {ASTNode} exponent The node to check.
|
40
|
+
* @returns {boolean} `true` if the node needs to be parenthesised.
|
41
|
+
*/
|
42
|
+
function doesExponentNeedParens(exponent) {
|
43
|
+
|
44
|
+
// '**' is right-associative, there is no need for parens when Math.pow(a, b ** c) is converted to a ** b ** c
|
45
|
+
return astUtils.getPrecedence(exponent) < PRECEDENCE_OF_EXPONENTIATION_EXPR;
|
46
|
+
}
|
47
|
+
|
48
|
+
/**
|
49
|
+
* Determines whether an exponentiation binary expression at the place of the given node would need parens.
|
50
|
+
* @param {ASTNode} node A node that would be replaced by an exponentiation binary expression.
|
51
|
+
* @param {SourceCode} sourceCode A SourceCode object.
|
52
|
+
* @returns {boolean} `true` if the expression needs to be parenthesised.
|
53
|
+
*/
|
54
|
+
function doesExponentiationExpressionNeedParens(node, sourceCode) {
|
55
|
+
const parent = node.parent;
|
56
|
+
|
57
|
+
const needsParens = (
|
58
|
+
parent.type === "ClassDeclaration" ||
|
59
|
+
(
|
60
|
+
parent.type.endsWith("Expression") &&
|
61
|
+
astUtils.getPrecedence(parent) >= PRECEDENCE_OF_EXPONENTIATION_EXPR &&
|
62
|
+
!(parent.type === "BinaryExpression" && parent.operator === "**" && parent.right === node) &&
|
63
|
+
!((parent.type === "CallExpression" || parent.type === "NewExpression") && parent.arguments.includes(node)) &&
|
64
|
+
!(parent.type === "MemberExpression" && parent.computed && parent.property === node) &&
|
65
|
+
!(parent.type === "ArrayExpression")
|
66
|
+
)
|
67
|
+
);
|
68
|
+
|
69
|
+
return needsParens && !astUtils.isParenthesised(sourceCode, node);
|
70
|
+
}
|
71
|
+
|
72
|
+
/**
|
73
|
+
* Optionally parenthesizes given text.
|
74
|
+
* @param {string} text The text to parenthesize.
|
75
|
+
* @param {boolean} shouldParenthesize If `true`, the text will be parenthesised.
|
76
|
+
* @returns {string} parenthesised or unchanged text.
|
77
|
+
*/
|
78
|
+
function parenthesizeIfShould(text, shouldParenthesize) {
|
79
|
+
return shouldParenthesize ? `(${text})` : text;
|
80
|
+
}
|
81
|
+
|
82
|
+
//------------------------------------------------------------------------------
|
83
|
+
// Rule Definition
|
84
|
+
//------------------------------------------------------------------------------
|
85
|
+
|
86
|
+
module.exports = {
|
87
|
+
meta: {
|
88
|
+
type: "suggestion",
|
89
|
+
|
90
|
+
docs: {
|
91
|
+
description: "disallow the use of `Math.pow` in favor of the `**` operator",
|
92
|
+
category: "Stylistic Issues",
|
93
|
+
recommended: false,
|
94
|
+
url: "https://eslint.org/docs/rules/prefer-exponentiation-operator"
|
95
|
+
},
|
96
|
+
|
97
|
+
schema: [],
|
98
|
+
fixable: "code",
|
99
|
+
|
100
|
+
messages: {
|
101
|
+
useExponentiation: "Use the '**' operator instead of 'Math.pow'."
|
102
|
+
}
|
103
|
+
},
|
104
|
+
|
105
|
+
create(context) {
|
106
|
+
const sourceCode = context.getSourceCode();
|
107
|
+
|
108
|
+
/**
|
109
|
+
* Reports the given node.
|
110
|
+
* @param {ASTNode} node 'Math.pow()' node to report.
|
111
|
+
* @returns {void}
|
112
|
+
*/
|
113
|
+
function report(node) {
|
114
|
+
context.report({
|
115
|
+
node,
|
116
|
+
messageId: "useExponentiation",
|
117
|
+
fix(fixer) {
|
118
|
+
if (
|
119
|
+
node.arguments.length !== 2 ||
|
120
|
+
node.arguments.some(arg => arg.type === "SpreadElement") ||
|
121
|
+
sourceCode.getCommentsInside(node).length > 0
|
122
|
+
) {
|
123
|
+
return null;
|
124
|
+
}
|
125
|
+
|
126
|
+
const base = node.arguments[0],
|
127
|
+
exponent = node.arguments[1],
|
128
|
+
baseText = sourceCode.getText(base),
|
129
|
+
exponentText = sourceCode.getText(exponent),
|
130
|
+
shouldParenthesizeBase = doesBaseNeedParens(base),
|
131
|
+
shouldParenthesizeExponent = doesExponentNeedParens(exponent),
|
132
|
+
shouldParenthesizeAll = doesExponentiationExpressionNeedParens(node, sourceCode);
|
133
|
+
|
134
|
+
let prefix = "",
|
135
|
+
suffix = "";
|
136
|
+
|
137
|
+
if (!shouldParenthesizeAll) {
|
138
|
+
if (!shouldParenthesizeBase) {
|
139
|
+
const firstReplacementToken = sourceCode.getFirstToken(base),
|
140
|
+
tokenBefore = sourceCode.getTokenBefore(node);
|
141
|
+
|
142
|
+
if (
|
143
|
+
tokenBefore &&
|
144
|
+
tokenBefore.range[1] === node.range[0] &&
|
145
|
+
!astUtils.canTokensBeAdjacent(tokenBefore, firstReplacementToken)
|
146
|
+
) {
|
147
|
+
prefix = " "; // a+Math.pow(++b, c) -> a+ ++b**c
|
148
|
+
}
|
149
|
+
}
|
150
|
+
if (!shouldParenthesizeExponent) {
|
151
|
+
const lastReplacementToken = sourceCode.getLastToken(exponent),
|
152
|
+
tokenAfter = sourceCode.getTokenAfter(node);
|
153
|
+
|
154
|
+
if (
|
155
|
+
tokenAfter &&
|
156
|
+
node.range[1] === tokenAfter.range[0] &&
|
157
|
+
!astUtils.canTokensBeAdjacent(lastReplacementToken, tokenAfter)
|
158
|
+
) {
|
159
|
+
suffix = " "; // Math.pow(a, b)in c -> a**b in c
|
160
|
+
}
|
161
|
+
}
|
162
|
+
}
|
163
|
+
|
164
|
+
const baseReplacement = parenthesizeIfShould(baseText, shouldParenthesizeBase),
|
165
|
+
exponentReplacement = parenthesizeIfShould(exponentText, shouldParenthesizeExponent),
|
166
|
+
replacement = parenthesizeIfShould(`${baseReplacement}**${exponentReplacement}`, shouldParenthesizeAll);
|
167
|
+
|
168
|
+
return fixer.replaceText(node, `${prefix}${replacement}${suffix}`);
|
169
|
+
}
|
170
|
+
});
|
171
|
+
}
|
172
|
+
|
173
|
+
return {
|
174
|
+
Program() {
|
175
|
+
const scope = context.getScope();
|
176
|
+
const tracker = new ReferenceTracker(scope);
|
177
|
+
const trackMap = {
|
178
|
+
Math: {
|
179
|
+
pow: { [CALL]: true }
|
180
|
+
}
|
181
|
+
};
|
182
|
+
|
183
|
+
for (const { node } of tracker.iterateGlobalReferences(trackMap)) {
|
184
|
+
report(node);
|
185
|
+
}
|
186
|
+
}
|
187
|
+
};
|
188
|
+
}
|
189
|
+
};
|
@@ -49,7 +49,6 @@ module.exports = {
|
|
49
49
|
|
50
50
|
/**
|
51
51
|
* Function to check regular expression.
|
52
|
-
*
|
53
52
|
* @param {string} pattern The regular expression pattern to be check.
|
54
53
|
* @param {ASTNode} node AST node which contains regular expression.
|
55
54
|
* @param {boolean} uFlag Flag indicates whether unicode mode is enabled or not.
|