eslint 5.0.1 → 5.4.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/CHANGELOG.md +84 -0
- package/README.md +1 -1
- package/conf/eslint-recommended.js +4 -0
- package/lib/cli-engine.js +38 -78
- package/lib/cli.js +1 -1
- package/lib/code-path-analysis/code-path-analyzer.js +2 -2
- package/lib/config/config-initializer.js +8 -8
- package/lib/config/config-validator.js +13 -6
- package/lib/config.js +1 -1
- package/lib/formatters/stylish.js +1 -1
- package/lib/ignored-paths.js +125 -37
- package/lib/linter.js +6 -7
- package/lib/rules/array-bracket-newline.js +1 -1
- package/lib/rules/array-bracket-spacing.js +1 -1
- package/lib/rules/array-callback-return.js +1 -1
- package/lib/rules/array-element-newline.js +1 -1
- package/lib/rules/arrow-body-style.js +1 -1
- package/lib/rules/arrow-parens.js +1 -1
- package/lib/rules/arrow-spacing.js +1 -1
- package/lib/rules/block-spacing.js +1 -1
- package/lib/rules/brace-style.js +1 -1
- package/lib/rules/capitalized-comments.js +1 -1
- package/lib/rules/comma-dangle.js +1 -1
- package/lib/rules/comma-spacing.js +1 -1
- package/lib/rules/comma-style.js +2 -2
- package/lib/rules/complexity.js +3 -3
- package/lib/rules/computed-property-spacing.js +1 -1
- package/lib/rules/consistent-return.js +1 -1
- package/lib/rules/curly.js +1 -1
- package/lib/rules/dot-location.js +1 -1
- package/lib/rules/dot-notation.js +1 -1
- package/lib/rules/eqeqeq.js +1 -1
- package/lib/rules/func-call-spacing.js +1 -1
- package/lib/rules/func-name-matching.js +1 -1
- package/lib/rules/func-names.js +1 -1
- package/lib/rules/function-paren-newline.js +1 -1
- package/lib/rules/getter-return.js +1 -1
- package/lib/rules/indent-legacy.js +1 -1
- package/lib/rules/indent.js +43 -7
- package/lib/rules/jsx-quotes.js +1 -1
- package/lib/rules/key-spacing.js +2 -2
- package/lib/rules/keyword-spacing.js +1 -1
- package/lib/rules/line-comment-position.js +3 -3
- package/lib/rules/linebreak-style.js +1 -1
- package/lib/rules/lines-around-comment.js +1 -1
- package/lib/rules/lines-around-directive.js +1 -1
- package/lib/rules/lines-between-class-members.js +1 -1
- package/lib/rules/max-depth.js +2 -2
- package/lib/rules/max-len.js +1 -1
- package/lib/rules/max-lines-per-function.js +1 -1
- package/lib/rules/max-lines.js +2 -2
- package/lib/rules/max-nested-callbacks.js +2 -2
- package/lib/rules/max-params.js +3 -3
- package/lib/rules/max-statements-per-line.js +1 -1
- package/lib/rules/max-statements.js +3 -3
- package/lib/rules/multiline-comment-style.js +1 -1
- package/lib/rules/multiline-ternary.js +1 -1
- package/lib/rules/new-parens.js +1 -1
- package/lib/rules/newline-after-var.js +1 -1
- package/lib/rules/newline-per-chained-call.js +1 -1
- package/lib/rules/no-alert.js +1 -1
- package/lib/rules/no-async-promise-executor.js +33 -0
- package/lib/rules/no-catch-shadow.js +5 -2
- package/lib/rules/no-class-assign.js +1 -1
- package/lib/rules/no-cond-assign.js +1 -1
- package/lib/rules/no-confusing-arrow.js +1 -1
- package/lib/rules/no-console.js +1 -1
- package/lib/rules/no-const-assign.js +1 -1
- package/lib/rules/no-debugger.js +2 -10
- package/lib/rules/no-dupe-keys.js +1 -1
- package/lib/rules/no-else-return.js +1 -1
- package/lib/rules/no-empty-function.js +1 -1
- package/lib/rules/no-empty.js +1 -1
- package/lib/rules/no-eval.js +1 -1
- package/lib/rules/no-ex-assign.js +1 -1
- package/lib/rules/no-extend-native.js +1 -1
- package/lib/rules/no-extra-bind.js +1 -1
- package/lib/rules/no-extra-boolean-cast.js +1 -1
- package/lib/rules/no-extra-label.js +1 -1
- package/lib/rules/no-extra-parens.js +2 -2
- package/lib/rules/no-extra-semi.js +1 -1
- package/lib/rules/no-floating-decimal.js +1 -1
- package/lib/rules/no-func-assign.js +1 -1
- package/lib/rules/no-implicit-coercion.js +1 -1
- package/lib/rules/no-inline-comments.js +1 -1
- package/lib/rules/no-invalid-this.js +1 -1
- package/lib/rules/no-irregular-whitespace.js +1 -1
- package/lib/rules/no-label-var.js +1 -1
- package/lib/rules/no-labels.js +1 -1
- package/lib/rules/no-misleading-character-class.js +189 -0
- package/lib/rules/no-mixed-operators.js +1 -1
- package/lib/rules/no-multi-spaces.js +1 -1
- package/lib/rules/no-multi-str.js +1 -1
- package/lib/rules/no-regex-spaces.js +1 -1
- package/lib/rules/no-restricted-globals.js +1 -1
- package/lib/rules/no-restricted-imports.js +1 -1
- package/lib/rules/no-restricted-modules.js +1 -1
- package/lib/rules/no-restricted-properties.js +1 -1
- package/lib/rules/no-return-assign.js +1 -1
- package/lib/rules/no-return-await.js +1 -1
- package/lib/rules/no-self-assign.js +1 -1
- package/lib/rules/no-sequences.js +1 -1
- package/lib/rules/no-shadow.js +1 -1
- package/lib/rules/no-this-before-super.js +1 -1
- package/lib/rules/no-throw-literal.js +1 -1
- package/lib/rules/no-trailing-spaces.js +1 -1
- package/lib/rules/no-undef-init.js +1 -1
- package/lib/rules/no-unexpected-multiline.js +1 -1
- package/lib/rules/no-unmodified-loop-condition.js +2 -3
- package/lib/rules/no-unneeded-ternary.js +1 -1
- package/lib/rules/no-unsafe-negation.js +1 -1
- package/lib/rules/no-unused-vars.js +1 -1
- package/lib/rules/no-useless-call.js +1 -1
- package/lib/rules/no-useless-computed-key.js +1 -1
- package/lib/rules/no-useless-concat.js +1 -1
- package/lib/rules/no-useless-escape.js +1 -1
- package/lib/rules/no-useless-return.js +2 -11
- package/lib/rules/no-var.js +1 -1
- package/lib/rules/no-warning-comments.js +1 -1
- package/lib/rules/no-whitespace-before-property.js +1 -1
- package/lib/rules/object-curly-newline.js +1 -1
- package/lib/rules/object-curly-spacing.js +1 -1
- package/lib/rules/object-shorthand.js +1 -1
- package/lib/rules/one-var.js +6 -6
- package/lib/rules/operator-assignment.js +1 -1
- package/lib/rules/operator-linebreak.js +1 -1
- package/lib/rules/padded-blocks.js +6 -6
- package/lib/rules/padding-line-between-statements.js +2 -2
- package/lib/rules/prefer-const.js +3 -12
- package/lib/rules/prefer-object-spread.js +154 -197
- package/lib/rules/prefer-promise-reject-errors.js +1 -1
- package/lib/rules/prefer-reflect.js +1 -1
- package/lib/rules/prefer-spread.js +1 -1
- package/lib/rules/prefer-template.js +1 -1
- package/lib/rules/quotes.js +1 -1
- package/lib/rules/radix.js +1 -1
- package/lib/rules/require-atomic-updates.js +239 -0
- package/lib/rules/require-await.js +1 -1
- package/lib/rules/require-unicode-regexp.js +65 -0
- package/lib/rules/semi-spacing.js +3 -3
- package/lib/rules/semi-style.js +1 -1
- package/lib/rules/semi.js +1 -1
- package/lib/rules/sort-keys.js +2 -2
- package/lib/rules/space-before-blocks.js +1 -1
- package/lib/rules/space-before-function-paren.js +1 -1
- package/lib/rules/space-in-parens.js +1 -1
- package/lib/rules/space-unary-ops.js +2 -2
- package/lib/rules/spaced-comment.js +1 -1
- package/lib/rules/strict.js +1 -1
- package/lib/rules/switch-colon-spacing.js +1 -1
- package/lib/rules/symbol-description.js +1 -1
- package/lib/rules/template-curly-spacing.js +1 -1
- package/lib/rules/valid-jsdoc.js +1 -1
- package/lib/rules/wrap-iife.js +1 -1
- package/lib/rules/wrap-regex.js +8 -4
- package/lib/rules/yoda.js +1 -1
- package/lib/testers/rule-tester.js +8 -10
- package/lib/token-store/index.js +1 -1
- package/lib/{ast-utils.js → util/ast-utils.js} +0 -0
- package/lib/{file-finder.js → util/file-finder.js} +2 -2
- package/lib/util/fix-tracker.js +1 -1
- package/lib/util/{glob-util.js → glob-utils.js} +4 -4
- package/lib/util/lint-result-cache.js +146 -0
- package/lib/{logging.js → util/logging.js} +0 -0
- package/lib/util/naming.js +2 -2
- package/lib/util/node-event-generator.js +3 -3
- package/lib/util/{npm-util.js → npm-utils.js} +1 -1
- package/lib/util/{path-util.js → path-utils.js} +1 -1
- package/lib/util/source-code-fixer.js +1 -1
- package/lib/util/{source-code-util.js → source-code-utils.js} +3 -3
- package/lib/util/source-code.js +1 -1
- package/lib/{timing.js → util/timing.js} +0 -0
- package/lib/util/unicode/index.js +11 -0
- package/lib/util/unicode/is-combining-character.js +13 -0
- package/lib/util/unicode/is-emoji-modifier.js +13 -0
- package/lib/util/unicode/is-regional-indicator-symbol.js +13 -0
- package/lib/util/unicode/is-surrogate-pair.js +14 -0
- package/package.json +6 -6
- package/lib/rules/.eslintrc.yml +0 -4
@@ -17,7 +17,7 @@ const OPTIONS = {
|
|
17
17
|
//------------------------------------------------------------------------------
|
18
18
|
// Requirements
|
19
19
|
//------------------------------------------------------------------------------
|
20
|
-
const astUtils = require("../ast-utils");
|
20
|
+
const astUtils = require("../util/ast-utils");
|
21
21
|
|
22
22
|
//------------------------------------------------------------------------------
|
23
23
|
// Rule Definition
|
package/lib/rules/one-var.js
CHANGED
@@ -74,19 +74,19 @@ module.exports = {
|
|
74
74
|
options.let = { uninitialized: mode, initialized: mode };
|
75
75
|
options.const = { uninitialized: mode, initialized: mode };
|
76
76
|
} else if (typeof mode === "object") { // options configuration is an object
|
77
|
-
if (
|
77
|
+
if (Object.prototype.hasOwnProperty.call(mode, "separateRequires")) {
|
78
78
|
options.separateRequires = !!mode.separateRequires;
|
79
79
|
}
|
80
|
-
if (
|
80
|
+
if (Object.prototype.hasOwnProperty.call(mode, "var")) {
|
81
81
|
options.var = { uninitialized: mode.var, initialized: mode.var };
|
82
82
|
}
|
83
|
-
if (
|
83
|
+
if (Object.prototype.hasOwnProperty.call(mode, "let")) {
|
84
84
|
options.let = { uninitialized: mode.let, initialized: mode.let };
|
85
85
|
}
|
86
|
-
if (
|
86
|
+
if (Object.prototype.hasOwnProperty.call(mode, "const")) {
|
87
87
|
options.const = { uninitialized: mode.const, initialized: mode.const };
|
88
88
|
}
|
89
|
-
if (
|
89
|
+
if (Object.prototype.hasOwnProperty.call(mode, "uninitialized")) {
|
90
90
|
if (!options.var) {
|
91
91
|
options.var = {};
|
92
92
|
}
|
@@ -100,7 +100,7 @@ module.exports = {
|
|
100
100
|
options.let.uninitialized = mode.uninitialized;
|
101
101
|
options.const.uninitialized = mode.uninitialized;
|
102
102
|
}
|
103
|
-
if (
|
103
|
+
if (Object.prototype.hasOwnProperty.call(mode, "initialized")) {
|
104
104
|
if (!options.var) {
|
105
105
|
options.var = {};
|
106
106
|
}
|
@@ -8,7 +8,7 @@
|
|
8
8
|
// Requirements
|
9
9
|
//------------------------------------------------------------------------------
|
10
10
|
|
11
|
-
const astUtils = require("../ast-utils");
|
11
|
+
const astUtils = require("../util/ast-utils");
|
12
12
|
|
13
13
|
//------------------------------------------------------------------------------
|
14
14
|
// Helpers
|
@@ -9,7 +9,7 @@
|
|
9
9
|
// Requirements
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
|
-
const astUtils = require("../ast-utils");
|
12
|
+
const astUtils = require("../util/ast-utils");
|
13
13
|
|
14
14
|
//------------------------------------------------------------------------------
|
15
15
|
// Rule Definition
|
@@ -58,13 +58,13 @@ module.exports = {
|
|
58
58
|
options.switches = shouldHavePadding;
|
59
59
|
options.classes = shouldHavePadding;
|
60
60
|
} else {
|
61
|
-
if (
|
61
|
+
if (Object.prototype.hasOwnProperty.call(config, "blocks")) {
|
62
62
|
options.blocks = config.blocks === "always";
|
63
63
|
}
|
64
|
-
if (
|
64
|
+
if (Object.prototype.hasOwnProperty.call(config, "switches")) {
|
65
65
|
options.switches = config.switches === "always";
|
66
66
|
}
|
67
|
-
if (
|
67
|
+
if (Object.prototype.hasOwnProperty.call(config, "classes")) {
|
68
68
|
options.classes = config.classes === "always";
|
69
69
|
}
|
70
70
|
}
|
@@ -225,7 +225,7 @@ module.exports = {
|
|
225
225
|
|
226
226
|
const rule = {};
|
227
227
|
|
228
|
-
if (
|
228
|
+
if (Object.prototype.hasOwnProperty.call(options, "switches")) {
|
229
229
|
rule.SwitchStatement = function(node) {
|
230
230
|
if (node.cases.length === 0) {
|
231
231
|
return;
|
@@ -234,7 +234,7 @@ module.exports = {
|
|
234
234
|
};
|
235
235
|
}
|
236
236
|
|
237
|
-
if (
|
237
|
+
if (Object.prototype.hasOwnProperty.call(options, "blocks")) {
|
238
238
|
rule.BlockStatement = function(node) {
|
239
239
|
if (node.body.length === 0) {
|
240
240
|
return;
|
@@ -243,7 +243,7 @@ module.exports = {
|
|
243
243
|
};
|
244
244
|
}
|
245
245
|
|
246
|
-
if (
|
246
|
+
if (Object.prototype.hasOwnProperty.call(options, "classes")) {
|
247
247
|
rule.ClassBody = function(node) {
|
248
248
|
if (node.body.length === 0) {
|
249
249
|
return;
|
@@ -9,7 +9,7 @@
|
|
9
9
|
// Requirements
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
|
-
const astUtils = require("../ast-utils");
|
12
|
+
const astUtils = require("../util/ast-utils");
|
13
13
|
|
14
14
|
//------------------------------------------------------------------------------
|
15
15
|
// Helpers
|
@@ -367,6 +367,7 @@ const StatementTypes = {
|
|
367
367
|
|
368
368
|
block: newNodeTypeTester("BlockStatement"),
|
369
369
|
empty: newNodeTypeTester("EmptyStatement"),
|
370
|
+
function: newNodeTypeTester("FunctionDeclaration"),
|
370
371
|
|
371
372
|
break: newKeywordTester("break"),
|
372
373
|
case: newKeywordTester("case"),
|
@@ -378,7 +379,6 @@ const StatementTypes = {
|
|
378
379
|
do: newKeywordTester("do"),
|
379
380
|
export: newKeywordTester("export"),
|
380
381
|
for: newKeywordTester("for"),
|
381
|
-
function: newKeywordTester("function"),
|
382
382
|
if: newKeywordTester("if"),
|
383
383
|
import: newKeywordTester("import"),
|
384
384
|
let: newKeywordTester("let"),
|
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
-
const astUtils = require("../ast-utils");
|
8
|
+
const astUtils = require("../util/ast-utils");
|
9
9
|
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
// Helpers
|
@@ -15,15 +15,6 @@ const PATTERN_TYPE = /^(?:.+?Pattern|RestElement|SpreadProperty|ExperimentalRest
|
|
15
15
|
const DECLARATION_HOST_TYPE = /^(?:Program|BlockStatement|SwitchCase)$/;
|
16
16
|
const DESTRUCTURING_HOST_TYPE = /^(?:VariableDeclarator|AssignmentExpression)$/;
|
17
17
|
|
18
|
-
/**
|
19
|
-
* Adds multiple items to the tail of an array.
|
20
|
-
*
|
21
|
-
* @param {any[]} array - A destination to add.
|
22
|
-
* @param {any[]} values - Items to be added.
|
23
|
-
* @returns {void}
|
24
|
-
*/
|
25
|
-
const pushAll = Function.apply.bind(Array.prototype.push);
|
26
|
-
|
27
18
|
/**
|
28
19
|
* Checks whether a given node is located at `ForStatement.init` or not.
|
29
20
|
*
|
@@ -170,7 +161,7 @@ function getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign) {
|
|
170
161
|
const elements = leftNode.elements;
|
171
162
|
|
172
163
|
hasOuterVariables = elements
|
173
|
-
.map(element => element.name)
|
164
|
+
.map(element => element && element.name)
|
174
165
|
.some(name => isOuterVariableInDestructing(name, variable.scope));
|
175
166
|
}
|
176
167
|
if (hasOuterVariables) {
|
@@ -364,7 +355,7 @@ module.exports = {
|
|
364
355
|
|
365
356
|
VariableDeclaration(node) {
|
366
357
|
if (node.kind === "let" && !isInitOfForStatement(node)) {
|
367
|
-
|
358
|
+
variables.push(...context.getDeclaredVariables(node));
|
368
359
|
}
|
369
360
|
}
|
370
361
|
};
|
@@ -6,21 +6,15 @@
|
|
6
6
|
|
7
7
|
"use strict";
|
8
8
|
|
9
|
-
const
|
9
|
+
const { CALL, ReferenceTracker } = require("eslint-utils");
|
10
|
+
const {
|
11
|
+
isCommaToken,
|
12
|
+
isOpeningParenToken,
|
13
|
+
isClosingParenToken,
|
14
|
+
isParenthesised
|
15
|
+
} = require("../util/ast-utils");
|
10
16
|
|
11
|
-
|
12
|
-
* Helper that checks if the node is an Object.assign call
|
13
|
-
* @param {ASTNode} node - The node that the rule warns on
|
14
|
-
* @returns {boolean} - Returns true if the node is an Object.assign call
|
15
|
-
*/
|
16
|
-
function isObjectAssign(node) {
|
17
|
-
return (
|
18
|
-
node.callee &&
|
19
|
-
node.callee.type === "MemberExpression" &&
|
20
|
-
node.callee.object.name === "Object" &&
|
21
|
-
node.callee.property.name === "assign"
|
22
|
-
);
|
23
|
-
}
|
17
|
+
const ANY_SPACE = /\s/;
|
24
18
|
|
25
19
|
/**
|
26
20
|
* Helper that checks if the Object.assign call has array spread
|
@@ -35,15 +29,12 @@ function hasArraySpread(node) {
|
|
35
29
|
* Helper that checks if the node needs parentheses to be valid JS.
|
36
30
|
* The default is to wrap the node in parentheses to avoid parsing errors.
|
37
31
|
* @param {ASTNode} node - The node that the rule warns on
|
32
|
+
* @param {Object} sourceCode - in context sourcecode object
|
38
33
|
* @returns {boolean} - Returns true if the node needs parentheses
|
39
34
|
*/
|
40
|
-
function needsParens(node) {
|
35
|
+
function needsParens(node, sourceCode) {
|
41
36
|
const parent = node.parent;
|
42
37
|
|
43
|
-
if (!parent || !node.type) {
|
44
|
-
return true;
|
45
|
-
}
|
46
|
-
|
47
38
|
switch (parent.type) {
|
48
39
|
case "VariableDeclarator":
|
49
40
|
case "ArrayExpression":
|
@@ -51,101 +42,102 @@ function needsParens(node) {
|
|
51
42
|
case "CallExpression":
|
52
43
|
case "Property":
|
53
44
|
return false;
|
45
|
+
case "AssignmentExpression":
|
46
|
+
return parent.left === node && !isParenthesised(sourceCode, node);
|
54
47
|
default:
|
55
|
-
return
|
48
|
+
return !isParenthesised(sourceCode, node);
|
56
49
|
}
|
57
50
|
}
|
58
51
|
|
59
52
|
/**
|
60
53
|
* Determines if an argument needs parentheses. The default is to not add parens.
|
61
54
|
* @param {ASTNode} node - The node to be checked.
|
55
|
+
* @param {Object} sourceCode - in context sourcecode object
|
62
56
|
* @returns {boolean} True if the node needs parentheses
|
63
57
|
*/
|
64
|
-
function argNeedsParens(node) {
|
65
|
-
if (!node.type) {
|
66
|
-
return false;
|
67
|
-
}
|
68
|
-
|
58
|
+
function argNeedsParens(node, sourceCode) {
|
69
59
|
switch (node.type) {
|
70
60
|
case "AssignmentExpression":
|
71
61
|
case "ArrowFunctionExpression":
|
72
62
|
case "ConditionalExpression":
|
73
|
-
return
|
63
|
+
return !isParenthesised(sourceCode, node);
|
74
64
|
default:
|
75
65
|
return false;
|
76
66
|
}
|
77
67
|
}
|
78
68
|
|
79
69
|
/**
|
80
|
-
*
|
81
|
-
*
|
82
|
-
* @param {
|
83
|
-
* @
|
70
|
+
* Get the parenthesis tokens of a given ObjectExpression node.
|
71
|
+
* This incldues the braces of the object literal and enclosing parentheses.
|
72
|
+
* @param {ASTNode} node The node to get.
|
73
|
+
* @param {Token} leftArgumentListParen The opening paren token of the argument list.
|
74
|
+
* @param {SourceCode} sourceCode The source code object to get tokens.
|
75
|
+
* @returns {Token[]} The parenthesis tokens of the node. This is sorted by the location.
|
84
76
|
*/
|
85
|
-
function
|
86
|
-
const
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
const commentEnd = arr[1];
|
103
|
-
|
104
|
-
if (insertIndex < commentStart || insertIndex > commentEnd) {
|
105
|
-
validWhitespaceMatches.push(insertIndex);
|
106
|
-
}
|
107
|
-
});
|
108
|
-
});
|
109
|
-
const insertPos = Math.max(...validWhitespaceMatches);
|
110
|
-
const regex = new RegExp(`^((?:.|[^/s/S]){${insertPos}}) *`);
|
77
|
+
function getParenTokens(node, leftArgumentListParen, sourceCode) {
|
78
|
+
const parens = [sourceCode.getFirstToken(node), sourceCode.getLastToken(node)];
|
79
|
+
let leftNext = sourceCode.getTokenBefore(node);
|
80
|
+
let rightNext = sourceCode.getTokenAfter(node);
|
81
|
+
|
82
|
+
// Note: don't include the parens of the argument list.
|
83
|
+
while (
|
84
|
+
leftNext &&
|
85
|
+
rightNext &&
|
86
|
+
leftNext.range[0] > leftArgumentListParen.range[0] &&
|
87
|
+
isOpeningParenToken(leftNext) &&
|
88
|
+
isClosingParenToken(rightNext)
|
89
|
+
) {
|
90
|
+
parens.push(leftNext, rightNext);
|
91
|
+
leftNext = sourceCode.getTokenBefore(leftNext);
|
92
|
+
rightNext = sourceCode.getTokenAfter(rightNext);
|
93
|
+
}
|
111
94
|
|
112
|
-
return
|
95
|
+
return parens.sort((a, b) => a.range[0] - b.range[0]);
|
113
96
|
}
|
114
97
|
|
115
98
|
/**
|
116
|
-
*
|
117
|
-
* @param {
|
118
|
-
* @param {
|
119
|
-
* @
|
120
|
-
* @param {array} comments - comments inside checked node
|
121
|
-
* @returns {string} - formatted argument
|
99
|
+
* Get the range of a given token and around whitespaces.
|
100
|
+
* @param {Token} token The token to get range.
|
101
|
+
* @param {SourceCode} sourceCode The source code object to get tokens.
|
102
|
+
* @returns {number} The end of the range of the token and around whitespaces.
|
122
103
|
*/
|
123
|
-
function
|
124
|
-
const text = sourceCode.
|
125
|
-
|
126
|
-
const spread = arg.type === "SpreadElement" ? "" : "...";
|
104
|
+
function getStartWithSpaces(token, sourceCode) {
|
105
|
+
const text = sourceCode.text;
|
106
|
+
let start = token.range[0];
|
127
107
|
|
128
|
-
|
129
|
-
|
108
|
+
// If the previous token is a line comment then skip this step to avoid commenting this token out.
|
109
|
+
{
|
110
|
+
const prevToken = sourceCode.getTokenBefore(token, { includeComments: true });
|
111
|
+
|
112
|
+
if (prevToken && prevToken.type === "Line") {
|
113
|
+
return start;
|
114
|
+
}
|
130
115
|
}
|
131
116
|
|
132
|
-
|
117
|
+
// Detect spaces before the token.
|
118
|
+
while (ANY_SPACE.test(text[start - 1] || "")) {
|
119
|
+
start -= 1;
|
120
|
+
}
|
133
121
|
|
134
|
-
|
135
|
-
|
136
|
-
* exists before the curly brace. It also does the same for the closing curly brace. This is to avoid
|
137
|
-
* having multiple spaces around the object expression depending on how the object properties are spaced.
|
138
|
-
*/
|
139
|
-
const formattedObjectLiteral = text.replace(/^(.*){ */, "$1").replace(/ *}([^}]*)$/, "$1");
|
122
|
+
return start;
|
123
|
+
}
|
140
124
|
|
141
|
-
|
142
|
-
|
125
|
+
/**
|
126
|
+
* Get the range of a given token and around whitespaces.
|
127
|
+
* @param {Token} token The token to get range.
|
128
|
+
* @param {SourceCode} sourceCode The source code object to get tokens.
|
129
|
+
* @returns {number} The start of the range of the token and around whitespaces.
|
130
|
+
*/
|
131
|
+
function getEndWithSpaces(token, sourceCode) {
|
132
|
+
const text = sourceCode.text;
|
133
|
+
let end = token.range[1];
|
143
134
|
|
144
|
-
|
145
|
-
|
135
|
+
// Detect spaces after the token.
|
136
|
+
while (ANY_SPACE.test(text[end] || "")) {
|
137
|
+
end += 1;
|
146
138
|
}
|
147
139
|
|
148
|
-
return
|
140
|
+
return end;
|
149
141
|
}
|
150
142
|
|
151
143
|
/**
|
@@ -154,77 +146,70 @@ function formatArg(arg, isLast, sourceCode, comments) {
|
|
154
146
|
* @param {string} sourceCode - sourceCode of the Object.assign call
|
155
147
|
* @returns {Function} autofixer - replaces the Object.assign with a spread object.
|
156
148
|
*/
|
157
|
-
function
|
158
|
-
return fixer
|
159
|
-
const
|
160
|
-
const
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
.
|
171
|
-
.
|
172
|
-
|
173
|
-
const insertBody = fixer.replaceTextRange([firstArg.range[0], lastArg.range[1]], handleArgs.join(""));
|
174
|
-
const replaceObjectAssignEnd = fixer.replaceTextRange([lastArg.range[1], node.range[1]], `${parens ? "})" : "}"}`);
|
175
|
-
|
176
|
-
return [
|
177
|
-
replaceObjectAssignStart,
|
178
|
-
insertBody,
|
179
|
-
replaceObjectAssignEnd
|
180
|
-
];
|
181
|
-
};
|
182
|
-
}
|
149
|
+
function defineFixer(node, sourceCode) {
|
150
|
+
return function *(fixer) {
|
151
|
+
const leftParen = sourceCode.getTokenAfter(node.callee, isOpeningParenToken);
|
152
|
+
const rightParen = sourceCode.getLastToken(node);
|
153
|
+
|
154
|
+
// Remove the callee `Object.assign`
|
155
|
+
yield fixer.remove(node.callee);
|
156
|
+
|
157
|
+
// Replace the parens of argument list to braces.
|
158
|
+
if (needsParens(node, sourceCode)) {
|
159
|
+
yield fixer.replaceText(leftParen, "({");
|
160
|
+
yield fixer.replaceText(rightParen, "})");
|
161
|
+
} else {
|
162
|
+
yield fixer.replaceText(leftParen, "{");
|
163
|
+
yield fixer.replaceText(rightParen, "}");
|
164
|
+
}
|
183
165
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
*/
|
190
|
-
function autofixObjectLiteral(node, sourceCode) {
|
191
|
-
return fixer => {
|
192
|
-
const argument = node.arguments[0];
|
193
|
-
const parens = needsParens(node);
|
166
|
+
// Process arguments.
|
167
|
+
for (const argNode of node.arguments) {
|
168
|
+
const innerParens = getParenTokens(argNode, leftParen, sourceCode);
|
169
|
+
const left = innerParens.shift();
|
170
|
+
const right = innerParens.pop();
|
194
171
|
|
195
|
-
|
196
|
-
|
197
|
-
|
172
|
+
if (argNode.type === "ObjectExpression") {
|
173
|
+
const maybeTrailingComma = sourceCode.getLastToken(argNode, 1);
|
174
|
+
const maybeArgumentComma = sourceCode.getTokenAfter(right);
|
198
175
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
176
|
+
/*
|
177
|
+
* Make bare this object literal.
|
178
|
+
* And remove spaces inside of the braces for better formatting.
|
179
|
+
*/
|
180
|
+
for (const innerParen of innerParens) {
|
181
|
+
yield fixer.remove(innerParen);
|
182
|
+
}
|
183
|
+
const leftRange = [left.range[0], getEndWithSpaces(left, sourceCode)];
|
184
|
+
const rightRange = [
|
185
|
+
Math.max(getStartWithSpaces(right, sourceCode), leftRange[1]), // Ensure ranges don't overlap
|
186
|
+
right.range[1]
|
187
|
+
];
|
208
188
|
|
209
|
-
|
210
|
-
|
211
|
-
node.type === "ImportDeclaration";
|
212
|
-
}
|
189
|
+
yield fixer.removeRange(leftRange);
|
190
|
+
yield fixer.removeRange(rightRange);
|
213
191
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
192
|
+
// Remove the comma of this argument if it's duplication.
|
193
|
+
if (
|
194
|
+
(argNode.properties.length === 0 || isCommaToken(maybeTrailingComma)) &&
|
195
|
+
isCommaToken(maybeArgumentComma)
|
196
|
+
) {
|
197
|
+
yield fixer.remove(maybeArgumentComma);
|
198
|
+
}
|
199
|
+
} else {
|
200
|
+
|
201
|
+
// Make spread.
|
202
|
+
if (argNeedsParens(argNode, sourceCode)) {
|
203
|
+
yield fixer.insertTextBefore(left, "...(");
|
204
|
+
yield fixer.insertTextAfter(right, ")");
|
205
|
+
} else {
|
206
|
+
yield fixer.insertTextBefore(left, "...");
|
207
|
+
}
|
208
|
+
}
|
209
|
+
}
|
210
|
+
};
|
225
211
|
}
|
226
212
|
|
227
|
-
|
228
213
|
module.exports = {
|
229
214
|
meta: {
|
230
215
|
docs: {
|
@@ -242,61 +227,33 @@ module.exports = {
|
|
242
227
|
}
|
243
228
|
},
|
244
229
|
|
245
|
-
create
|
230
|
+
create(context) {
|
246
231
|
const sourceCode = context.getSourceCode();
|
247
|
-
const scope = context.getScope();
|
248
|
-
const objectVariable = scope.variables.filter(variable => variable.name === "Object");
|
249
|
-
const moduleReferences = scope.childScopes.filter(childScope => {
|
250
|
-
const varNamedObject = childScope.variables.filter(variable => variable.name === "Object");
|
251
|
-
|
252
|
-
return childScope.type === "module" && varNamedObject.length;
|
253
|
-
});
|
254
|
-
const references = [].concat(...objectVariable.map(variable => variable.references || []));
|
255
232
|
|
256
233
|
return {
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
node,
|
279
|
-
|
280
|
-
fix: autofixObjectLiteral(node, sourceCode)
|
281
|
-
});
|
282
|
-
}
|
283
|
-
|
284
|
-
/*
|
285
|
-
* The condition below warns on `Object.assign` calls that that have
|
286
|
-
* an object literal as the first argument and have a second argument
|
287
|
-
* that can be spread. e.g `Object.assign({ foo: bar }, baz)`
|
288
|
-
*/
|
289
|
-
if (
|
290
|
-
node.arguments.length > 1 &&
|
291
|
-
node.arguments[0].type === "ObjectExpression" &&
|
292
|
-
isObjectAssign(node) &&
|
293
|
-
!hasArraySpread(node)
|
294
|
-
) {
|
295
|
-
context.report({
|
296
|
-
node,
|
297
|
-
messageId: "useSpreadMessage",
|
298
|
-
fix: autofixSpread(node, sourceCode)
|
299
|
-
});
|
234
|
+
Program() {
|
235
|
+
const scope = context.getScope();
|
236
|
+
const tracker = new ReferenceTracker(scope);
|
237
|
+
const trackMap = {
|
238
|
+
Object: {
|
239
|
+
assign: { [CALL]: true }
|
240
|
+
}
|
241
|
+
};
|
242
|
+
|
243
|
+
// Iterate all calls of `Object.assign` (only of the global variable `Object`).
|
244
|
+
for (const { node } of tracker.iterateGlobalReferences(trackMap)) {
|
245
|
+
if (
|
246
|
+
node.arguments.length >= 1 &&
|
247
|
+
node.arguments[0].type === "ObjectExpression" &&
|
248
|
+
!hasArraySpread(node)
|
249
|
+
) {
|
250
|
+
const messageId = node.arguments.length === 1
|
251
|
+
? "useLiteralMessage"
|
252
|
+
: "useSpreadMessage";
|
253
|
+
const fix = defineFixer(node, sourceCode);
|
254
|
+
|
255
|
+
context.report({ node, messageId, fix });
|
256
|
+
}
|
300
257
|
}
|
301
258
|
}
|
302
259
|
};
|
@@ -98,7 +98,7 @@ module.exports = {
|
|
98
98
|
CallExpression(node) {
|
99
99
|
const methodName = (node.callee.property || {}).name;
|
100
100
|
const isReflectCall = (node.callee.object || {}).name === "Reflect";
|
101
|
-
const hasReflectSubsitute =
|
101
|
+
const hasReflectSubsitute = Object.prototype.hasOwnProperty.call(reflectSubsitutes, methodName);
|
102
102
|
const userConfiguredException = exceptions.indexOf(methodName) !== -1;
|
103
103
|
|
104
104
|
if (hasReflectSubsitute && !isReflectCall && !userConfiguredException) {
|