eslint 5.0.0 → 5.3.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.
Files changed (169) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/README.md +1 -1
  3. package/conf/eslint-recommended.js +4 -0
  4. package/lib/cli-engine.js +37 -76
  5. package/lib/cli.js +1 -1
  6. package/lib/code-path-analysis/code-path-analyzer.js +2 -2
  7. package/lib/config/config-initializer.js +8 -8
  8. package/lib/config/config-validator.js +13 -6
  9. package/lib/config.js +1 -1
  10. package/lib/formatters/stylish.js +1 -1
  11. package/lib/ignored-paths.js +125 -37
  12. package/lib/linter.js +6 -7
  13. package/lib/rules/array-bracket-newline.js +1 -1
  14. package/lib/rules/array-bracket-spacing.js +1 -1
  15. package/lib/rules/array-callback-return.js +1 -1
  16. package/lib/rules/array-element-newline.js +1 -1
  17. package/lib/rules/arrow-body-style.js +1 -1
  18. package/lib/rules/arrow-parens.js +1 -1
  19. package/lib/rules/arrow-spacing.js +1 -1
  20. package/lib/rules/block-spacing.js +1 -1
  21. package/lib/rules/brace-style.js +1 -1
  22. package/lib/rules/capitalized-comments.js +1 -1
  23. package/lib/rules/comma-dangle.js +1 -1
  24. package/lib/rules/comma-spacing.js +1 -1
  25. package/lib/rules/comma-style.js +1 -1
  26. package/lib/rules/complexity.js +1 -1
  27. package/lib/rules/computed-property-spacing.js +1 -1
  28. package/lib/rules/consistent-return.js +1 -1
  29. package/lib/rules/curly.js +1 -1
  30. package/lib/rules/dot-location.js +1 -1
  31. package/lib/rules/dot-notation.js +1 -1
  32. package/lib/rules/eqeqeq.js +1 -1
  33. package/lib/rules/func-call-spacing.js +1 -1
  34. package/lib/rules/func-name-matching.js +1 -1
  35. package/lib/rules/func-names.js +1 -1
  36. package/lib/rules/function-paren-newline.js +1 -1
  37. package/lib/rules/getter-return.js +1 -1
  38. package/lib/rules/indent-legacy.js +1 -1
  39. package/lib/rules/indent.js +37 -5
  40. package/lib/rules/jsx-quotes.js +1 -1
  41. package/lib/rules/key-spacing.js +2 -2
  42. package/lib/rules/keyword-spacing.js +1 -1
  43. package/lib/rules/line-comment-position.js +2 -2
  44. package/lib/rules/linebreak-style.js +1 -1
  45. package/lib/rules/lines-around-comment.js +1 -1
  46. package/lib/rules/lines-around-directive.js +1 -1
  47. package/lib/rules/lines-between-class-members.js +1 -1
  48. package/lib/rules/max-len.js +1 -1
  49. package/lib/rules/max-lines-per-function.js +1 -1
  50. package/lib/rules/max-lines.js +1 -1
  51. package/lib/rules/max-params.js +1 -1
  52. package/lib/rules/max-statements-per-line.js +1 -1
  53. package/lib/rules/max-statements.js +1 -1
  54. package/lib/rules/multiline-comment-style.js +1 -1
  55. package/lib/rules/multiline-ternary.js +1 -1
  56. package/lib/rules/new-parens.js +1 -1
  57. package/lib/rules/newline-after-var.js +1 -1
  58. package/lib/rules/newline-per-chained-call.js +1 -1
  59. package/lib/rules/no-alert.js +1 -1
  60. package/lib/rules/no-async-promise-executor.js +33 -0
  61. package/lib/rules/no-catch-shadow.js +5 -2
  62. package/lib/rules/no-class-assign.js +1 -1
  63. package/lib/rules/no-cond-assign.js +1 -1
  64. package/lib/rules/no-confusing-arrow.js +1 -1
  65. package/lib/rules/no-console.js +1 -1
  66. package/lib/rules/no-const-assign.js +1 -1
  67. package/lib/rules/no-debugger.js +2 -10
  68. package/lib/rules/no-dupe-keys.js +1 -1
  69. package/lib/rules/no-else-return.js +1 -1
  70. package/lib/rules/no-empty-function.js +1 -1
  71. package/lib/rules/no-empty.js +1 -1
  72. package/lib/rules/no-eval.js +1 -1
  73. package/lib/rules/no-ex-assign.js +1 -1
  74. package/lib/rules/no-extend-native.js +1 -1
  75. package/lib/rules/no-extra-bind.js +1 -1
  76. package/lib/rules/no-extra-boolean-cast.js +1 -1
  77. package/lib/rules/no-extra-label.js +1 -1
  78. package/lib/rules/no-extra-parens.js +1 -1
  79. package/lib/rules/no-extra-semi.js +1 -1
  80. package/lib/rules/no-floating-decimal.js +1 -1
  81. package/lib/rules/no-func-assign.js +1 -1
  82. package/lib/rules/no-implicit-coercion.js +1 -1
  83. package/lib/rules/no-inline-comments.js +1 -1
  84. package/lib/rules/no-invalid-this.js +1 -1
  85. package/lib/rules/no-irregular-whitespace.js +1 -1
  86. package/lib/rules/no-label-var.js +1 -1
  87. package/lib/rules/no-labels.js +1 -1
  88. package/lib/rules/no-misleading-character-class.js +189 -0
  89. package/lib/rules/no-mixed-operators.js +1 -1
  90. package/lib/rules/no-multi-spaces.js +1 -1
  91. package/lib/rules/no-multi-str.js +1 -1
  92. package/lib/rules/no-regex-spaces.js +1 -1
  93. package/lib/rules/no-restricted-properties.js +1 -1
  94. package/lib/rules/no-return-assign.js +1 -1
  95. package/lib/rules/no-return-await.js +1 -1
  96. package/lib/rules/no-self-assign.js +1 -1
  97. package/lib/rules/no-sequences.js +1 -1
  98. package/lib/rules/no-shadow.js +1 -1
  99. package/lib/rules/no-this-before-super.js +1 -1
  100. package/lib/rules/no-throw-literal.js +1 -1
  101. package/lib/rules/no-trailing-spaces.js +1 -1
  102. package/lib/rules/no-undef-init.js +1 -1
  103. package/lib/rules/no-unexpected-multiline.js +1 -1
  104. package/lib/rules/no-unmodified-loop-condition.js +2 -3
  105. package/lib/rules/no-unneeded-ternary.js +1 -1
  106. package/lib/rules/no-unsafe-negation.js +1 -1
  107. package/lib/rules/no-unused-vars.js +1 -1
  108. package/lib/rules/no-useless-call.js +1 -1
  109. package/lib/rules/no-useless-computed-key.js +1 -1
  110. package/lib/rules/no-useless-concat.js +1 -1
  111. package/lib/rules/no-useless-escape.js +1 -1
  112. package/lib/rules/no-useless-return.js +2 -11
  113. package/lib/rules/no-var.js +1 -1
  114. package/lib/rules/no-warning-comments.js +1 -1
  115. package/lib/rules/no-whitespace-before-property.js +1 -1
  116. package/lib/rules/object-curly-newline.js +1 -1
  117. package/lib/rules/object-curly-spacing.js +1 -1
  118. package/lib/rules/object-shorthand.js +1 -1
  119. package/lib/rules/operator-assignment.js +1 -1
  120. package/lib/rules/operator-linebreak.js +1 -1
  121. package/lib/rules/padding-line-between-statements.js +2 -2
  122. package/lib/rules/prefer-const.js +3 -12
  123. package/lib/rules/prefer-object-spread.js +154 -197
  124. package/lib/rules/prefer-promise-reject-errors.js +1 -1
  125. package/lib/rules/prefer-spread.js +1 -1
  126. package/lib/rules/prefer-template.js +1 -1
  127. package/lib/rules/quotes.js +1 -1
  128. package/lib/rules/radix.js +1 -1
  129. package/lib/rules/require-atomic-updates.js +239 -0
  130. package/lib/rules/require-await.js +1 -1
  131. package/lib/rules/require-unicode-regexp.js +65 -0
  132. package/lib/rules/semi-spacing.js +1 -1
  133. package/lib/rules/semi-style.js +1 -1
  134. package/lib/rules/semi.js +1 -1
  135. package/lib/rules/sort-keys.js +2 -2
  136. package/lib/rules/space-before-blocks.js +1 -1
  137. package/lib/rules/space-before-function-paren.js +1 -1
  138. package/lib/rules/space-in-parens.js +1 -1
  139. package/lib/rules/space-unary-ops.js +1 -1
  140. package/lib/rules/spaced-comment.js +1 -1
  141. package/lib/rules/strict.js +1 -1
  142. package/lib/rules/switch-colon-spacing.js +1 -1
  143. package/lib/rules/symbol-description.js +1 -1
  144. package/lib/rules/template-curly-spacing.js +1 -1
  145. package/lib/rules/valid-jsdoc.js +1 -1
  146. package/lib/rules/wrap-iife.js +1 -1
  147. package/lib/rules/wrap-regex.js +8 -4
  148. package/lib/rules/yoda.js +1 -1
  149. package/lib/testers/rule-tester.js +3 -5
  150. package/lib/token-store/index.js +1 -1
  151. package/lib/{ast-utils.js → util/ast-utils.js} +0 -0
  152. package/lib/{file-finder.js → util/file-finder.js} +0 -0
  153. package/lib/util/fix-tracker.js +1 -1
  154. package/lib/util/{glob-util.js → glob-utils.js} +4 -4
  155. package/lib/util/lint-result-cache.js +146 -0
  156. package/lib/{logging.js → util/logging.js} +0 -0
  157. package/lib/util/naming.js +2 -2
  158. package/lib/util/node-event-generator.js +3 -3
  159. package/lib/util/{npm-util.js → npm-utils.js} +1 -1
  160. package/lib/util/{path-util.js → path-utils.js} +1 -1
  161. package/lib/util/{source-code-util.js → source-code-utils.js} +3 -3
  162. package/lib/util/source-code.js +1 -1
  163. package/lib/{timing.js → util/timing.js} +0 -0
  164. package/lib/util/unicode/index.js +11 -0
  165. package/lib/util/unicode/is-combining-character.js +13 -0
  166. package/lib/util/unicode/is-emoji-modifier.js +13 -0
  167. package/lib/util/unicode/is-regional-indicator-symbol.js +13 -0
  168. package/lib/util/unicode/is-surrogate-pair.js +14 -0
  169. package/package.json +6 -5
@@ -6,21 +6,15 @@
6
6
 
7
7
  "use strict";
8
8
 
9
- const matchAll = require("string.prototype.matchall");
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 true;
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 true;
63
+ return !isParenthesised(sourceCode, node);
74
64
  default:
75
65
  return false;
76
66
  }
77
67
  }
78
68
 
79
69
  /**
80
- * Helper that adds a comma after the last non-whitespace character that is not a part of a comment.
81
- * @param {string} formattedArg - String of argument text
82
- * @param {array} comments - comments inside the argument
83
- * @returns {string} - argument with comma at the end of it
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 addComma(formattedArg, comments) {
86
- const nonWhitespaceCharacterRegex = /[^\s\\]/g;
87
- const nonWhitespaceCharacters = Array.from(matchAll(formattedArg, nonWhitespaceCharacterRegex));
88
- const commentRanges = comments.map(comment => comment.range);
89
- const validWhitespaceMatches = [];
90
-
91
- // Create a list of indexes where non-whitespace characters exist.
92
- nonWhitespaceCharacters.forEach(match => {
93
- const insertIndex = match.index + match[0].length;
94
-
95
- if (!commentRanges.length) {
96
- validWhitespaceMatches.push(insertIndex);
97
- }
98
-
99
- // If comment ranges are found make sure that the non whitespace characters are not part of the comment.
100
- commentRanges.forEach(arr => {
101
- const commentStart = arr[0];
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 formattedArg.replace(regex, "$1, ");
95
+ return parens.sort((a, b) => a.range[0] - b.range[0]);
113
96
  }
114
97
 
115
98
  /**
116
- * Helper formats an argument by either removing curlies or adding a spread operator
117
- * @param {ASTNode|null} arg - ast node representing argument to format
118
- * @param {boolean} isLast - true if on the last element of the array
119
- * @param {Object} sourceCode - in context sourcecode object
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 formatArg(arg, isLast, sourceCode, comments) {
124
- const text = sourceCode.getText(arg);
125
- const parens = argNeedsParens(arg);
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
- if (arg.type === "ObjectExpression" && arg.properties.length === 0) {
129
- return "";
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
- if (arg.type === "ObjectExpression") {
117
+ // Detect spaces before the token.
118
+ while (ANY_SPACE.test(text[start - 1] || "")) {
119
+ start -= 1;
120
+ }
133
121
 
134
- /**
135
- * This regex finds the opening curly brace and any following spaces and replaces it with whatever
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
- return isLast ? formattedObjectLiteral : addComma(formattedObjectLiteral, comments);
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
- if (isLast) {
145
- return parens ? `${spread}(${text})` : `${spread}${text}`;
135
+ // Detect spaces after the token.
136
+ while (ANY_SPACE.test(text[end] || "")) {
137
+ end += 1;
146
138
  }
147
139
 
148
- return parens ? addComma(`${spread}(${text})`, comments) : `${spread}${addComma(text, comments)}`;
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 autofixSpread(node, sourceCode) {
158
- return fixer => {
159
- const args = node.arguments;
160
- const firstArg = args[0];
161
- const lastArg = args[args.length - 1];
162
- const parens = needsParens(node);
163
- const comments = sourceCode.getCommentsInside(node);
164
- const replaceObjectAssignStart = fixer.replaceTextRange(
165
- [node.range[0], firstArg.range[0]],
166
- `${parens ? "({" : "{"}`
167
- );
168
-
169
- const handleArgs = args
170
- .map((arg, i, arr) => formatArg(arg, i + 1 >= arr.length, sourceCode, comments))
171
- .filter(arg => arg !== "," && arg !== "");
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
- * Autofixes the Object.assign call with a single object literal as an argument
186
- * @param {ASTNode|null} node - The node that the rule warns on, i.e. the Object.assign call
187
- * @param {string} sourceCode - sourceCode of the Object.assign call
188
- * @returns {Function} autofixer - replaces the Object.assign with a object literal.
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
- return fixer.replaceText(node, `${parens ? "(" : ""}${sourceCode.text.slice(argument.range[0], argument.range[1])}${parens ? ")" : ""}`);
196
- };
197
- }
172
+ if (argNode.type === "ObjectExpression") {
173
+ const maybeTrailingComma = sourceCode.getLastToken(argNode, 1);
174
+ const maybeArgumentComma = sourceCode.getTokenAfter(right);
198
175
 
199
- /**
200
- * Check if the node has modified a given variable
201
- * @param {ASTNode|null} node - The node that the rule warns on, i.e. the Object.assign call
202
- * @returns {boolean} - true if node is an assignment, variable declaration, or import statement
203
- */
204
- function isModifier(node) {
205
- if (!node.type) {
206
- return false;
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
- return node.type === "AssignmentExpression" ||
210
- node.type === "VariableDeclarator" ||
211
- node.type === "ImportDeclaration";
212
- }
189
+ yield fixer.removeRange(leftRange);
190
+ yield fixer.removeRange(rightRange);
213
191
 
214
- /**
215
- * Check if the node has modified a given variable
216
- * @param {array} references - list of reference nodes
217
- * @returns {boolean} - true if node is has been overwritten by an assignment or import
218
- */
219
- function modifyingObjectReference(references) {
220
- return references.some(ref => (
221
- ref.identifier &&
222
- ref.identifier.parent &&
223
- isModifier(ref.identifier.parent)
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: function rule(context) {
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
- CallExpression(node) {
258
-
259
- /*
260
- * If current file is either importing Object or redefining it,
261
- * we skip warning on this rule.
262
- */
263
- if (moduleReferences.length || (references.length && modifyingObjectReference(references))) {
264
- return;
265
- }
266
-
267
- /*
268
- * The condition below is cases where Object.assign has a single argument and
269
- * that argument is an object literal. e.g. `Object.assign({ foo: bar })`.
270
- * For now, we will warn on this case and autofix it.
271
- */
272
- if (
273
- node.arguments.length === 1 &&
274
- node.arguments[0].type === "ObjectExpression" &&
275
- isObjectAssign(node)
276
- ) {
277
- context.report({
278
- node,
279
- messageId: "useLiteralMessage",
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
  };
@@ -4,7 +4,7 @@
4
4
  */
5
5
  "use strict";
6
6
 
7
- const astUtils = require("../ast-utils");
7
+ const astUtils = require("../util/ast-utils");
8
8
 
9
9
  //------------------------------------------------------------------------------
10
10
  // Rule Definition
@@ -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
@@ -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
@@ -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
  // Constants
@@ -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