eslint 7.0.0-alpha.3 → 7.2.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 (89) hide show
  1. package/CHANGELOG.md +303 -0
  2. package/README.md +10 -11
  3. package/bin/eslint.js +115 -77
  4. package/conf/category-list.json +0 -1
  5. package/lib/api.js +2 -0
  6. package/lib/cli-engine/cascading-config-array-factory.js +12 -0
  7. package/lib/cli-engine/cli-engine.js +53 -48
  8. package/lib/cli-engine/config-array/config-array.js +1 -1
  9. package/lib/cli-engine/config-array/ignore-pattern.js +7 -1
  10. package/lib/cli-engine/config-array-factory.js +3 -3
  11. package/lib/cli.js +181 -95
  12. package/lib/eslint/eslint.js +656 -0
  13. package/lib/eslint/index.js +7 -0
  14. package/lib/init/autoconfig.js +4 -4
  15. package/lib/init/config-initializer.js +5 -10
  16. package/lib/init/source-code-utils.js +2 -2
  17. package/lib/linter/code-path-analysis/code-path-analyzer.js +2 -2
  18. package/lib/linter/code-path-analysis/code-path-state.js +34 -12
  19. package/lib/linter/config-comment-parser.js +1 -1
  20. package/lib/linter/linter.js +2 -1
  21. package/lib/options.js +0 -1
  22. package/lib/rule-tester/rule-tester.js +6 -1
  23. package/lib/rules/accessor-pairs.js +1 -1
  24. package/lib/rules/array-callback-return.js +3 -18
  25. package/lib/rules/arrow-parens.js +19 -3
  26. package/lib/rules/block-spacing.js +19 -2
  27. package/lib/rules/callback-return.js +4 -0
  28. package/lib/rules/comma-style.js +3 -8
  29. package/lib/rules/func-call-spacing.js +22 -6
  30. package/lib/rules/getter-return.js +2 -12
  31. package/lib/rules/global-require.js +4 -0
  32. package/lib/rules/handle-callback-err.js +4 -0
  33. package/lib/rules/index.js +1 -0
  34. package/lib/rules/key-spacing.js +1 -1
  35. package/lib/rules/keyword-spacing.js +9 -2
  36. package/lib/rules/linebreak-style.js +8 -2
  37. package/lib/rules/max-lines-per-function.js +1 -1
  38. package/lib/rules/multiline-ternary.js +44 -25
  39. package/lib/rules/new-cap.js +1 -1
  40. package/lib/rules/newline-per-chained-call.js +6 -3
  41. package/lib/rules/no-buffer-constructor.js +4 -0
  42. package/lib/rules/no-control-regex.js +1 -1
  43. package/lib/rules/no-empty-function.js +1 -1
  44. package/lib/rules/no-extra-boolean-cast.js +3 -0
  45. package/lib/rules/no-extra-parens.js +35 -3
  46. package/lib/rules/no-inner-declarations.js +31 -39
  47. package/lib/rules/no-invalid-regexp.js +1 -1
  48. package/lib/rules/no-lone-blocks.js +1 -1
  49. package/lib/rules/no-loss-of-precision.js +198 -0
  50. package/lib/rules/no-misleading-character-class.js +1 -1
  51. package/lib/rules/no-mixed-operators.js +3 -2
  52. package/lib/rules/no-mixed-requires.js +4 -0
  53. package/lib/rules/no-mixed-spaces-and-tabs.js +14 -6
  54. package/lib/rules/no-new-func.js +22 -19
  55. package/lib/rules/no-new-object.js +15 -3
  56. package/lib/rules/no-new-require.js +4 -0
  57. package/lib/rules/no-new-symbol.js +2 -1
  58. package/lib/rules/no-path-concat.js +4 -0
  59. package/lib/rules/no-process-env.js +4 -0
  60. package/lib/rules/no-process-exit.js +4 -0
  61. package/lib/rules/no-regex-spaces.js +1 -1
  62. package/lib/rules/no-restricted-exports.js +6 -0
  63. package/lib/rules/no-restricted-modules.js +4 -0
  64. package/lib/rules/no-sync.js +4 -0
  65. package/lib/rules/no-unexpected-multiline.js +22 -12
  66. package/lib/rules/no-unneeded-ternary.js +6 -4
  67. package/lib/rules/no-unused-expressions.js +1 -1
  68. package/lib/rules/no-unused-vars.js +3 -1
  69. package/lib/rules/no-useless-backreference.js +1 -1
  70. package/lib/rules/no-useless-concat.js +1 -1
  71. package/lib/rules/one-var-declaration-per-line.js +1 -1
  72. package/lib/rules/padded-blocks.js +17 -4
  73. package/lib/rules/prefer-named-capture-group.js +1 -1
  74. package/lib/rules/quote-props.js +2 -2
  75. package/lib/rules/rest-spread-spacing.js +3 -6
  76. package/lib/rules/semi-spacing.js +32 -8
  77. package/lib/rules/space-before-function-paren.js +5 -2
  78. package/lib/rules/template-tag-spacing.js +8 -2
  79. package/lib/rules/utils/ast-utils.js +106 -9
  80. package/lib/rules/yoda.js +101 -51
  81. package/lib/shared/relative-module-resolver.js +1 -0
  82. package/lib/shared/types.js +7 -0
  83. package/lib/source-code/source-code.js +1 -0
  84. package/messages/extend-config-missing.txt +1 -1
  85. package/messages/no-config-found.txt +1 -1
  86. package/messages/plugin-conflict.txt +1 -1
  87. package/messages/plugin-missing.txt +1 -1
  88. package/messages/whitespace-found.txt +1 -1
  89. package/package.json +27 -26
@@ -29,26 +29,29 @@ module.exports = {
29
29
 
30
30
  create(context) {
31
31
 
32
- //--------------------------------------------------------------------------
33
- // Helpers
34
- //--------------------------------------------------------------------------
35
-
36
- /**
37
- * Reports a node.
38
- * @param {ASTNode} node The node to report
39
- * @returns {void}
40
- * @private
41
- */
42
- function report(node) {
43
- context.report({
44
- node,
45
- messageId: "noFunctionConstructor"
46
- });
47
- }
48
-
49
32
  return {
50
- "NewExpression[callee.name = 'Function']": report,
51
- "CallExpression[callee.name = 'Function']": report
33
+ "Program:exit"() {
34
+ const globalScope = context.getScope();
35
+ const variable = globalScope.set.get("Function");
36
+
37
+ if (variable && variable.defs.length === 0) {
38
+ variable.references.forEach(ref => {
39
+ const node = ref.identifier;
40
+ const { parent } = node;
41
+
42
+ if (
43
+ parent &&
44
+ (parent.type === "NewExpression" || parent.type === "CallExpression") &&
45
+ node === parent.callee
46
+ ) {
47
+ context.report({
48
+ node: parent,
49
+ messageId: "noFunctionConstructor"
50
+ });
51
+ }
52
+ });
53
+ }
54
+ }
52
55
  };
53
56
 
54
57
  }
@@ -5,6 +5,12 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ //------------------------------------------------------------------------------
9
+ // Requirements
10
+ //------------------------------------------------------------------------------
11
+
12
+ const astUtils = require("./utils/ast-utils");
13
+
8
14
  //------------------------------------------------------------------------------
9
15
  // Rule Definition
10
16
  //------------------------------------------------------------------------------
@@ -28,10 +34,17 @@ module.exports = {
28
34
  },
29
35
 
30
36
  create(context) {
31
-
32
37
  return {
33
-
34
38
  NewExpression(node) {
39
+ const variable = astUtils.getVariableByName(
40
+ context.getScope(),
41
+ node.callee.name
42
+ );
43
+
44
+ if (variable && variable.identifiers.length > 0) {
45
+ return;
46
+ }
47
+
35
48
  if (node.callee.name === "Object") {
36
49
  context.report({
37
50
  node,
@@ -40,6 +53,5 @@ module.exports = {
40
53
  }
41
54
  }
42
55
  };
43
-
44
56
  }
45
57
  };
@@ -11,6 +11,10 @@
11
11
 
12
12
  module.exports = {
13
13
  meta: {
14
+ deprecated: true,
15
+
16
+ replacedBy: [],
17
+
14
18
  type: "suggestion",
15
19
 
16
20
  docs: {
@@ -37,8 +37,9 @@ module.exports = {
37
37
  if (variable && variable.defs.length === 0) {
38
38
  variable.references.forEach(ref => {
39
39
  const node = ref.identifier;
40
+ const parent = node.parent;
40
41
 
41
- if (node.parent && node.parent.type === "NewExpression") {
42
+ if (parent && parent.type === "NewExpression" && parent.callee === node) {
42
43
  context.report({
43
44
  node,
44
45
  messageId: "noNewSymbol"
@@ -10,6 +10,10 @@
10
10
 
11
11
  module.exports = {
12
12
  meta: {
13
+ deprecated: true,
14
+
15
+ replacedBy: [],
16
+
13
17
  type: "suggestion",
14
18
 
15
19
  docs: {
@@ -10,6 +10,10 @@
10
10
 
11
11
  module.exports = {
12
12
  meta: {
13
+ deprecated: true,
14
+
15
+ replacedBy: [],
16
+
13
17
  type: "suggestion",
14
18
 
15
19
  docs: {
@@ -10,6 +10,10 @@
10
10
 
11
11
  module.exports = {
12
12
  meta: {
13
+ deprecated: true,
14
+
15
+ replacedBy: [],
16
+
13
17
  type: "suggestion",
14
18
 
15
19
  docs: {
@@ -76,7 +76,7 @@ module.exports = {
76
76
 
77
77
  try {
78
78
  regExpAST = regExpParser.parsePattern(pattern, 0, pattern.length, flags.includes("u"));
79
- } catch (e) {
79
+ } catch {
80
80
 
81
81
  // Ignore regular expressions with syntax errors
82
82
  return;
@@ -61,6 +61,12 @@ module.exports = {
61
61
  }
62
62
 
63
63
  return {
64
+ ExportAllDeclaration(node) {
65
+ if (node.exported) {
66
+ checkExportedName(node.exported);
67
+ }
68
+ },
69
+
64
70
  ExportNamedDeclaration(node) {
65
71
  const declaration = node.declaration;
66
72
 
@@ -40,6 +40,10 @@ const arrayOfStringsOrObjects = {
40
40
 
41
41
  module.exports = {
42
42
  meta: {
43
+ deprecated: true,
44
+
45
+ replacedBy: [],
46
+
43
47
  type: "suggestion",
44
48
 
45
49
  docs: {
@@ -13,6 +13,10 @@
13
13
 
14
14
  module.exports = {
15
15
  meta: {
16
+ deprecated: true,
17
+
18
+ replacedBy: [],
19
+
16
20
  type: "suggestion",
17
21
 
18
22
  docs: {
@@ -53,7 +53,11 @@ module.exports = {
53
53
  const nodeExpressionEnd = sourceCode.getTokenBefore(openParen);
54
54
 
55
55
  if (openParen.loc.start.line !== nodeExpressionEnd.loc.end.line) {
56
- context.report({ node, loc: openParen.loc.start, messageId, data: { char: openParen.value } });
56
+ context.report({
57
+ node,
58
+ loc: openParen.loc,
59
+ messageId
60
+ });
57
61
  }
58
62
  }
59
63
 
@@ -71,18 +75,24 @@ module.exports = {
71
75
  },
72
76
 
73
77
  TaggedTemplateExpression(node) {
74
- if (node.tag.loc.end.line === node.quasi.loc.start.line) {
75
- return;
76
- }
77
-
78
- // handle generics type parameters on template tags
79
- const tokenBefore = sourceCode.getTokenBefore(node.quasi);
80
-
81
- if (tokenBefore.loc.end.line === node.quasi.loc.start.line) {
82
- return;
78
+ const { quasi } = node;
79
+
80
+ // handles common tags, parenthesized tags, and typescript's generic type arguments
81
+ const tokenBefore = sourceCode.getTokenBefore(quasi);
82
+
83
+ if (tokenBefore.loc.end.line !== quasi.loc.start.line) {
84
+ context.report({
85
+ node,
86
+ loc: {
87
+ start: quasi.loc.start,
88
+ end: {
89
+ line: quasi.loc.start.line,
90
+ column: quasi.loc.start.column + 1
91
+ }
92
+ },
93
+ messageId: "taggedTemplate"
94
+ });
83
95
  }
84
-
85
- context.report({ node, loc: node.loc.start, messageId: "taggedTemplate" });
86
96
  },
87
97
 
88
98
  CallExpression(node) {
@@ -147,10 +147,12 @@ module.exports = {
147
147
  loc: node.consequent.loc.start,
148
148
  messageId: "unnecessaryConditionalAssignment",
149
149
  fix: fixer => {
150
- const shouldParenthesizeAlternate = (
151
- astUtils.getPrecedence(node.alternate) < OR_PRECEDENCE &&
152
- !astUtils.isParenthesised(sourceCode, node.alternate)
153
- );
150
+ const shouldParenthesizeAlternate =
151
+ (
152
+ astUtils.getPrecedence(node.alternate) < OR_PRECEDENCE ||
153
+ astUtils.isCoalesceExpression(node.alternate)
154
+ ) &&
155
+ !astUtils.isParenthesised(sourceCode, node.alternate);
154
156
  const alternateText = shouldParenthesizeAlternate
155
157
  ? `(${sourceCode.getText(node.alternate)})`
156
158
  : astUtils.getParenthesisedText(sourceCode, node.alternate);
@@ -124,7 +124,7 @@ module.exports = {
124
124
  return true;
125
125
  }
126
126
 
127
- return /^(?:Assignment|Call|New|Update|Yield|Await)Expression$/u.test(node.type) ||
127
+ return /^(?:Assignment|Call|New|Update|Yield|Await|Import)Expression$/u.test(node.type) ||
128
128
  (node.type === "UnaryExpression" && ["delete", "void"].indexOf(node.operator) >= 0);
129
129
  }
130
130
 
@@ -619,7 +619,9 @@ module.exports = {
619
619
  // Report the first declaration.
620
620
  if (unusedVar.defs.length > 0) {
621
621
  context.report({
622
- node: unusedVar.identifiers[0],
622
+ node: unusedVar.references.length ? unusedVar.references[
623
+ unusedVar.references.length - 1
624
+ ].identifier : unusedVar.identifiers[0],
623
625
  messageId: "unusedVar",
624
626
  data: unusedVar.references.some(ref => ref.isWrite())
625
627
  ? getAssignedMessageData(unusedVar)
@@ -95,7 +95,7 @@ module.exports = {
95
95
 
96
96
  try {
97
97
  regExpAST = parser.parsePattern(pattern, 0, pattern.length, flags.includes("u"));
98
- } catch (e) {
98
+ } catch {
99
99
 
100
100
  // Ignore regular expressions with syntax errors
101
101
  return;
@@ -105,7 +105,7 @@ module.exports = {
105
105
 
106
106
  context.report({
107
107
  node,
108
- loc: operatorToken.loc.start,
108
+ loc: operatorToken.loc,
109
109
  messageId: "unexpectedConcat"
110
110
  });
111
111
  }
@@ -71,7 +71,7 @@ module.exports = {
71
71
  context.report({
72
72
  node,
73
73
  messageId: "expectVarOnNewline",
74
- loc: current.loc.start,
74
+ loc: current.loc,
75
75
  fix: fixer => fixer.insertTextBefore(current, "\n")
76
76
  });
77
77
  }
@@ -203,10 +203,14 @@ module.exports = {
203
203
  }
204
204
 
205
205
  if (requirePaddingFor(node)) {
206
+
206
207
  if (!blockHasTopPadding) {
207
208
  context.report({
208
209
  node,
209
- loc: { line: tokenBeforeFirst.loc.start.line, column: tokenBeforeFirst.loc.start.column },
210
+ loc: {
211
+ start: tokenBeforeFirst.loc.start,
212
+ end: firstBlockToken.loc.start
213
+ },
210
214
  fix(fixer) {
211
215
  return fixer.insertTextAfter(tokenBeforeFirst, "\n");
212
216
  },
@@ -216,7 +220,10 @@ module.exports = {
216
220
  if (!blockHasBottomPadding) {
217
221
  context.report({
218
222
  node,
219
- loc: { line: tokenAfterLast.loc.end.line, column: tokenAfterLast.loc.end.column - 1 },
223
+ loc: {
224
+ end: tokenAfterLast.loc.start,
225
+ start: lastBlockToken.loc.end
226
+ },
220
227
  fix(fixer) {
221
228
  return fixer.insertTextBefore(tokenAfterLast, "\n");
222
229
  },
@@ -228,7 +235,10 @@ module.exports = {
228
235
 
229
236
  context.report({
230
237
  node,
231
- loc: { line: tokenBeforeFirst.loc.start.line, column: tokenBeforeFirst.loc.start.column },
238
+ loc: {
239
+ start: tokenBeforeFirst.loc.start,
240
+ end: firstBlockToken.loc.start
241
+ },
232
242
  fix(fixer) {
233
243
  return fixer.replaceTextRange([tokenBeforeFirst.range[1], firstBlockToken.range[0] - firstBlockToken.loc.start.column], "\n");
234
244
  },
@@ -240,7 +250,10 @@ module.exports = {
240
250
 
241
251
  context.report({
242
252
  node,
243
- loc: { line: tokenAfterLast.loc.end.line, column: tokenAfterLast.loc.end.column - 1 },
253
+ loc: {
254
+ end: tokenAfterLast.loc.start,
255
+ start: lastBlockToken.loc.end
256
+ },
244
257
  messageId: "neverPadBlock",
245
258
  fix(fixer) {
246
259
  return fixer.replaceTextRange([lastBlockToken.range[1], tokenAfterLast.range[0] - tokenAfterLast.loc.start.column], "\n");
@@ -59,7 +59,7 @@ module.exports = {
59
59
 
60
60
  try {
61
61
  ast = parser.parsePattern(pattern, 0, pattern.length, uFlag);
62
- } catch (_) {
62
+ } catch {
63
63
 
64
64
  // ignore regex syntax errors
65
65
  return;
@@ -154,7 +154,7 @@ module.exports = {
154
154
 
155
155
  try {
156
156
  tokens = espree.tokenize(key.value);
157
- } catch (e) {
157
+ } catch {
158
158
  return;
159
159
  }
160
160
 
@@ -239,7 +239,7 @@ module.exports = {
239
239
 
240
240
  try {
241
241
  tokens = espree.tokenize(key.value);
242
- } catch (e) {
242
+ } catch {
243
243
  necessaryQuotes = true;
244
244
  return;
245
245
  }
@@ -79,10 +79,7 @@ module.exports = {
79
79
  if (alwaysSpace && !hasWhitespace) {
80
80
  context.report({
81
81
  node,
82
- loc: {
83
- line: operator.loc.end.line,
84
- column: operator.loc.end.column
85
- },
82
+ loc: operator.loc,
86
83
  messageId: "expectedWhitespace",
87
84
  data: {
88
85
  type
@@ -95,8 +92,8 @@ module.exports = {
95
92
  context.report({
96
93
  node,
97
94
  loc: {
98
- line: operator.loc.end.line,
99
- column: operator.loc.end.column
95
+ start: operator.loc.end,
96
+ end: nextToken.loc.start
100
97
  },
101
98
  messageId: "unexpectedWhitespace",
102
99
  data: {
@@ -117,6 +117,18 @@ module.exports = {
117
117
  }
118
118
 
119
119
  /**
120
+ * Report location example :
121
+ *
122
+ * for unexpected space `before`
123
+ *
124
+ * var a = 'b' ;
125
+ * ^^^
126
+ *
127
+ * for unexpected space `after`
128
+ *
129
+ * var a = 'b'; c = 10;
130
+ * ^^
131
+ *
120
132
  * Reports if the given token has invalid spacing.
121
133
  * @param {Token} token The semicolon token to check.
122
134
  * @param {ASTNode} node The corresponding node of the token.
@@ -124,16 +136,19 @@ module.exports = {
124
136
  */
125
137
  function checkSemicolonSpacing(token, node) {
126
138
  if (astUtils.isSemicolonToken(token)) {
127
- const location = token.loc.start;
128
-
129
139
  if (hasLeadingSpace(token)) {
130
140
  if (!requireSpaceBefore) {
141
+ const tokenBefore = sourceCode.getTokenBefore(token);
142
+ const loc = {
143
+ start: tokenBefore.loc.end,
144
+ end: token.loc.start
145
+ };
146
+
131
147
  context.report({
132
148
  node,
133
- loc: location,
149
+ loc,
134
150
  messageId: "unexpectedWhitespaceBefore",
135
151
  fix(fixer) {
136
- const tokenBefore = sourceCode.getTokenBefore(token);
137
152
 
138
153
  return fixer.removeRange([tokenBefore.range[1], token.range[0]]);
139
154
  }
@@ -141,9 +156,11 @@ module.exports = {
141
156
  }
142
157
  } else {
143
158
  if (requireSpaceBefore) {
159
+ const loc = token.loc;
160
+
144
161
  context.report({
145
162
  node,
146
- loc: location,
163
+ loc,
147
164
  messageId: "missingWhitespaceBefore",
148
165
  fix(fixer) {
149
166
  return fixer.insertTextBefore(token, " ");
@@ -155,12 +172,17 @@ module.exports = {
155
172
  if (!isFirstTokenInCurrentLine(token) && !isLastTokenInCurrentLine(token) && !isBeforeClosingParen(token)) {
156
173
  if (hasTrailingSpace(token)) {
157
174
  if (!requireSpaceAfter) {
175
+ const tokenAfter = sourceCode.getTokenAfter(token);
176
+ const loc = {
177
+ start: token.loc.end,
178
+ end: tokenAfter.loc.start
179
+ };
180
+
158
181
  context.report({
159
182
  node,
160
- loc: location,
183
+ loc,
161
184
  messageId: "unexpectedWhitespaceAfter",
162
185
  fix(fixer) {
163
- const tokenAfter = sourceCode.getTokenAfter(token);
164
186
 
165
187
  return fixer.removeRange([token.range[1], tokenAfter.range[0]]);
166
188
  }
@@ -168,9 +190,11 @@ module.exports = {
168
190
  }
169
191
  } else {
170
192
  if (requireSpaceAfter) {
193
+ const loc = token.loc;
194
+
171
195
  context.report({
172
196
  node,
173
- loc: location,
197
+ loc,
174
198
  messageId: "missingWhitespaceAfter",
175
199
  fix(fixer) {
176
200
  return fixer.insertTextAfter(token, " ");
@@ -127,7 +127,10 @@ module.exports = {
127
127
  if (hasSpacing && functionConfig === "never") {
128
128
  context.report({
129
129
  node,
130
- loc: leftToken.loc.end,
130
+ loc: {
131
+ start: leftToken.loc.end,
132
+ end: rightToken.loc.start
133
+ },
131
134
  messageId: "unexpectedSpace",
132
135
  fix(fixer) {
133
136
  const comments = sourceCode.getCommentsBefore(rightToken);
@@ -145,7 +148,7 @@ module.exports = {
145
148
  } else if (!hasSpacing && functionConfig === "always") {
146
149
  context.report({
147
150
  node,
148
- loc: leftToken.loc.end,
151
+ loc: rightToken.loc,
149
152
  messageId: "missingSpace",
150
153
  fix: fixer => fixer.insertTextAfter(leftToken, " ")
151
154
  });
@@ -49,7 +49,10 @@ module.exports = {
49
49
  if (never && hasWhitespace) {
50
50
  context.report({
51
51
  node,
52
- loc: tagToken.loc.start,
52
+ loc: {
53
+ start: tagToken.loc.end,
54
+ end: literalToken.loc.start
55
+ },
53
56
  messageId: "unexpected",
54
57
  fix(fixer) {
55
58
  const comments = sourceCode.getCommentsBefore(node.quasi);
@@ -68,7 +71,10 @@ module.exports = {
68
71
  } else if (!never && !hasWhitespace) {
69
72
  context.report({
70
73
  node,
71
- loc: tagToken.loc.start,
74
+ loc: {
75
+ start: node.loc.start,
76
+ end: literalToken.loc.start
77
+ },
72
78
  messageId: "missing",
73
79
  fix(fixer) {
74
80
  return fixer.insertTextAfter(tagToken, " ");