eslint 7.1.0 → 7.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/README.md +12 -7
  3. package/lib/cli-engine/cli-engine.js +2 -2
  4. package/lib/cli-engine/config-array-factory.js +1 -1
  5. package/lib/init/config-initializer.js +91 -74
  6. package/lib/linter/code-path-analysis/code-path-analyzer.js +2 -2
  7. package/lib/linter/code-path-analysis/code-path-state.js +34 -12
  8. package/lib/linter/config-comment-parser.js +1 -1
  9. package/lib/rule-tester/rule-tester.js +9 -0
  10. package/lib/rules/array-callback-return.js +21 -10
  11. package/lib/rules/arrow-body-style.js +2 -2
  12. package/lib/rules/arrow-parens.js +91 -108
  13. package/lib/rules/camelcase.js +47 -0
  14. package/lib/rules/comma-dangle.js +2 -1
  15. package/lib/rules/curly.js +8 -1
  16. package/lib/rules/func-call-spacing.js +18 -3
  17. package/lib/rules/{id-blacklist.js → id-denylist.js} +12 -12
  18. package/lib/rules/id-match.js +2 -1
  19. package/lib/rules/index.js +6 -1
  20. package/lib/rules/key-spacing.js +6 -2
  21. package/lib/rules/keyword-spacing.js +9 -2
  22. package/lib/rules/max-lines.js +34 -8
  23. package/lib/rules/multiline-ternary.js +44 -25
  24. package/lib/rules/no-control-regex.js +1 -1
  25. package/lib/rules/no-extra-boolean-cast.js +3 -0
  26. package/lib/rules/no-extra-parens.js +50 -4
  27. package/lib/rules/no-invalid-regexp.js +1 -1
  28. package/lib/rules/no-misleading-character-class.js +1 -1
  29. package/lib/rules/no-mixed-operators.js +3 -2
  30. package/lib/rules/no-mixed-spaces-and-tabs.js +14 -6
  31. package/lib/rules/no-promise-executor-return.js +121 -0
  32. package/lib/rules/no-regex-spaces.js +1 -1
  33. package/lib/rules/no-restricted-exports.js +6 -0
  34. package/lib/rules/no-unneeded-ternary.js +6 -4
  35. package/lib/rules/no-unreachable-loop.js +150 -0
  36. package/lib/rules/no-unused-expressions.js +1 -1
  37. package/lib/rules/no-unused-vars.js +5 -2
  38. package/lib/rules/no-useless-backreference.js +1 -1
  39. package/lib/rules/object-property-newline.js +1 -1
  40. package/lib/rules/operator-linebreak.js +2 -5
  41. package/lib/rules/padded-blocks.js +2 -1
  42. package/lib/rules/prefer-named-capture-group.js +1 -1
  43. package/lib/rules/prefer-regex-literals.js +66 -8
  44. package/lib/rules/quote-props.js +2 -2
  45. package/lib/rules/semi-spacing.js +1 -0
  46. package/lib/rules/template-tag-spacing.js +8 -2
  47. package/lib/rules/utils/ast-utils.js +55 -3
  48. package/package.json +6 -6
@@ -644,6 +644,10 @@ class RuleTester {
644
644
  assert.ok(item.errors || item.errors === 0,
645
645
  `Did not specify errors for an invalid test of ${ruleName}`);
646
646
 
647
+ if (Array.isArray(item.errors) && item.errors.length === 0) {
648
+ assert.fail("Invalid cases must have at least one error");
649
+ }
650
+
647
651
  const ruleHasMetaMessages = hasOwnProperty(rule, "meta") && hasOwnProperty(rule.meta, "messages");
648
652
  const friendlyIDList = ruleHasMetaMessages ? `[${Object.keys(rule.meta.messages).map(key => `'${key}'`).join(", ")}]` : null;
649
653
 
@@ -651,6 +655,11 @@ class RuleTester {
651
655
  const messages = result.messages;
652
656
 
653
657
  if (typeof item.errors === "number") {
658
+
659
+ if (item.errors === 0) {
660
+ assert.fail("Invalid cases must have 'error' value greater than 0");
661
+ }
662
+
654
663
  assert.strictEqual(messages.length, item.errors, util.format("Should have %d error%s but had %d: %s",
655
664
  item.errors, item.errors === 1 ? "" : "s", messages.length, util.inspect(messages)));
656
665
  } else {
@@ -9,8 +9,6 @@
9
9
  // Requirements
10
10
  //------------------------------------------------------------------------------
11
11
 
12
- const lodash = require("lodash");
13
-
14
12
  const astUtils = require("./utils/ast-utils");
15
13
 
16
14
  //------------------------------------------------------------------------------
@@ -43,6 +41,19 @@ function isTargetMethod(node) {
43
41
  );
44
42
  }
45
43
 
44
+ /**
45
+ * Returns a human-legible description of an array method
46
+ * @param {string} arrayMethodName A method name to fully qualify
47
+ * @returns {string} the method name prefixed with `Array.` if it is a class method,
48
+ * or else `Array.prototype.` if it is an instance method.
49
+ */
50
+ function fullMethodName(arrayMethodName) {
51
+ if (["from", "of", "isArray"].includes(arrayMethodName)) {
52
+ return "Array.".concat(arrayMethodName);
53
+ }
54
+ return "Array.prototype.".concat(arrayMethodName);
55
+ }
56
+
46
57
  /**
47
58
  * Checks whether or not a given node is a function expression which is the
48
59
  * callback of an array method, returning the method name.
@@ -153,10 +164,10 @@ module.exports = {
153
164
  ],
154
165
 
155
166
  messages: {
156
- expectedAtEnd: "Expected to return a value at the end of {{name}}.",
157
- expectedInside: "Expected to return a value in {{name}}.",
158
- expectedReturnValue: "{{name}} expected a return value.",
159
- expectedNoReturnValue: "{{name}} did not expect a return value."
167
+ expectedAtEnd: "{{arrayMethodName}}() expects a value to be returned at the end of {{name}}.",
168
+ expectedInside: "{{arrayMethodName}}() expects a return value from {{name}}.",
169
+ expectedReturnValue: "{{arrayMethodName}}() expects a return value from {{name}}.",
170
+ expectedNoReturnValue: "{{arrayMethodName}}() expects no useless return value from {{name}}."
160
171
  }
161
172
  },
162
173
 
@@ -202,14 +213,13 @@ module.exports = {
202
213
  }
203
214
 
204
215
  if (messageId) {
205
- let name = astUtils.getFunctionNameWithKind(node);
216
+ const name = astUtils.getFunctionNameWithKind(node);
206
217
 
207
- name = messageId === "expectedNoReturnValue" ? lodash.upperFirst(name) : name;
208
218
  context.report({
209
219
  node,
210
220
  loc: astUtils.getFunctionHeadLoc(node, sourceCode),
211
221
  messageId,
212
- data: { name }
222
+ data: { name, arrayMethodName: fullMethodName(funcInfo.arrayMethodName) }
213
223
  });
214
224
  }
215
225
  }
@@ -273,7 +283,8 @@ module.exports = {
273
283
  node,
274
284
  messageId,
275
285
  data: {
276
- name: lodash.upperFirst(astUtils.getFunctionNameWithKind(funcInfo.node))
286
+ name: astUtils.getFunctionNameWithKind(funcInfo.node),
287
+ arrayMethodName: fullMethodName(funcInfo.arrayMethodName)
277
288
  }
278
289
  });
279
290
  }
@@ -136,7 +136,7 @@ module.exports = {
136
136
 
137
137
  context.report({
138
138
  node,
139
- loc: arrowBody.loc.start,
139
+ loc: arrowBody.loc,
140
140
  messageId,
141
141
  fix(fixer) {
142
142
  const fixes = [];
@@ -201,7 +201,7 @@ module.exports = {
201
201
  if (always || (asNeeded && requireReturnForObjectLiteral && arrowBody.type === "ObjectExpression")) {
202
202
  context.report({
203
203
  node,
204
- loc: arrowBody.loc.start,
204
+ loc: arrowBody.loc,
205
205
  messageId: "expectedBlock",
206
206
  fix(fixer) {
207
207
  const fixes = [];
@@ -15,15 +15,12 @@ const astUtils = require("./utils/ast-utils");
15
15
  //------------------------------------------------------------------------------
16
16
 
17
17
  /**
18
- * Get location should be reported by AST node.
19
- * @param {ASTNode} node AST Node.
20
- * @returns {Location} Location information.
18
+ * Determines if the given arrow function has block body.
19
+ * @param {ASTNode} node `ArrowFunctionExpression` node.
20
+ * @returns {boolean} `true` if the function has block body.
21
21
  */
22
- function getLocation(node) {
23
- return {
24
- start: node.params[0].loc.start,
25
- end: node.params[node.params.length - 1].loc.end
26
- };
22
+ function hasBlockBody(node) {
23
+ return node.body.type === "BlockStatement";
27
24
  }
28
25
 
29
26
  //------------------------------------------------------------------------------
@@ -75,126 +72,112 @@ module.exports = {
75
72
  const sourceCode = context.getSourceCode();
76
73
 
77
74
  /**
78
- * Determines whether a arrow function argument end with `)`
79
- * @param {ASTNode} node The arrow function node.
80
- * @returns {void}
75
+ * Finds opening paren of parameters for the given arrow function, if it exists.
76
+ * It is assumed that the given arrow function has exactly one parameter.
77
+ * @param {ASTNode} node `ArrowFunctionExpression` node.
78
+ * @returns {Token|null} the opening paren, or `null` if the given arrow function doesn't have parens of parameters.
81
79
  */
82
- function parens(node) {
83
- const isAsync = node.async;
84
- const firstTokenOfParam = sourceCode.getFirstToken(node, isAsync ? 1 : 0);
85
-
86
- /**
87
- * Remove the parenthesis around a parameter
88
- * @param {Fixer} fixer Fixer
89
- * @returns {string} fixed parameter
90
- */
91
- function fixParamsWithParenthesis(fixer) {
92
- const paramToken = sourceCode.getTokenAfter(firstTokenOfParam);
93
-
94
- /*
95
- * ES8 allows Trailing commas in function parameter lists and calls
96
- * https://github.com/eslint/eslint/issues/8834
97
- */
98
- const closingParenToken = sourceCode.getTokenAfter(paramToken, astUtils.isClosingParenToken);
99
- const asyncToken = isAsync ? sourceCode.getTokenBefore(firstTokenOfParam) : null;
100
- const shouldAddSpaceForAsync = asyncToken && (asyncToken.range[1] === firstTokenOfParam.range[0]);
101
-
102
- return fixer.replaceTextRange([
103
- firstTokenOfParam.range[0],
104
- closingParenToken.range[1]
105
- ], `${shouldAddSpaceForAsync ? " " : ""}${paramToken.value}`);
80
+ function findOpeningParenOfParams(node) {
81
+ const tokenBeforeParams = sourceCode.getTokenBefore(node.params[0]);
82
+
83
+ if (
84
+ tokenBeforeParams &&
85
+ astUtils.isOpeningParenToken(tokenBeforeParams) &&
86
+ node.range[0] <= tokenBeforeParams.range[0]
87
+ ) {
88
+ return tokenBeforeParams;
106
89
  }
107
90
 
108
- /**
109
- * Checks whether there are comments inside the params or not.
110
- * @returns {boolean} `true` if there are comments inside of parens, else `false`
111
- */
112
- function hasCommentsInParens() {
113
- if (astUtils.isOpeningParenToken(firstTokenOfParam)) {
114
- const closingParenToken = sourceCode.getTokenAfter(node.params[0], astUtils.isClosingParenToken);
91
+ return null;
92
+ }
115
93
 
116
- return closingParenToken && sourceCode.commentsExistBetween(firstTokenOfParam, closingParenToken);
117
- }
118
- return false;
94
+ /**
95
+ * Finds closing paren of parameters for the given arrow function.
96
+ * It is assumed that the given arrow function has parens of parameters and that it has exactly one parameter.
97
+ * @param {ASTNode} node `ArrowFunctionExpression` node.
98
+ * @returns {Token} the closing paren of parameters.
99
+ */
100
+ function getClosingParenOfParams(node) {
101
+ return sourceCode.getTokenAfter(node.params[0], astUtils.isClosingParenToken);
102
+ }
119
103
 
120
- }
104
+ /**
105
+ * Determines whether the given arrow function has comments inside parens of parameters.
106
+ * It is assumed that the given arrow function has parens of parameters.
107
+ * @param {ASTNode} node `ArrowFunctionExpression` node.
108
+ * @param {Token} openingParen Opening paren of parameters.
109
+ * @returns {boolean} `true` if the function has at least one comment inside of parens of parameters.
110
+ */
111
+ function hasCommentsInParensOfParams(node, openingParen) {
112
+ return sourceCode.commentsExistBetween(openingParen, getClosingParenOfParams(node));
113
+ }
121
114
 
122
- if (hasCommentsInParens()) {
123
- return;
124
- }
115
+ /**
116
+ * Determines whether the given arrow function has unexpected tokens before opening paren of parameters,
117
+ * in which case it will be assumed that the existing parens of parameters are necessary.
118
+ * Only tokens within the range of the arrow function (tokens that are part of the arrow function) are taken into account.
119
+ * Example: <T>(a) => b
120
+ * @param {ASTNode} node `ArrowFunctionExpression` node.
121
+ * @param {Token} openingParen Opening paren of parameters.
122
+ * @returns {boolean} `true` if the function has at least one unexpected token.
123
+ */
124
+ function hasUnexpectedTokensBeforeOpeningParen(node, openingParen) {
125
+ const expectedCount = node.async ? 1 : 0;
125
126
 
126
- // "as-needed", { "requireForBlockBody": true }: x => x
127
- if (
128
- requireForBlockBody &&
129
- node.params[0].type === "Identifier" &&
130
- !node.params[0].typeAnnotation &&
131
- node.body.type !== "BlockStatement" &&
132
- !node.returnType
133
- ) {
134
- if (astUtils.isOpeningParenToken(firstTokenOfParam)) {
135
- context.report({
136
- node,
137
- messageId: "unexpectedParensInline",
138
- loc: getLocation(node),
139
- fix: fixParamsWithParenthesis
140
- });
141
- }
142
- return;
143
- }
127
+ return sourceCode.getFirstToken(node, { skip: expectedCount }) !== openingParen;
128
+ }
144
129
 
145
- if (
146
- requireForBlockBody &&
147
- node.body.type === "BlockStatement"
148
- ) {
149
- if (!astUtils.isOpeningParenToken(firstTokenOfParam)) {
150
- context.report({
151
- node,
152
- messageId: "expectedParensBlock",
153
- loc: getLocation(node),
154
- fix(fixer) {
155
- return fixer.replaceText(firstTokenOfParam, `(${firstTokenOfParam.value})`);
156
- }
157
- });
158
- }
159
- return;
160
- }
130
+ return {
131
+ "ArrowFunctionExpression[params.length=1]"(node) {
132
+ const shouldHaveParens = !asNeeded || requireForBlockBody && hasBlockBody(node);
133
+ const openingParen = findOpeningParenOfParams(node);
134
+ const hasParens = openingParen !== null;
135
+ const [param] = node.params;
161
136
 
162
- // "as-needed": x => x
163
- if (asNeeded &&
164
- node.params[0].type === "Identifier" &&
165
- !node.params[0].typeAnnotation &&
166
- !node.returnType
167
- ) {
168
- if (astUtils.isOpeningParenToken(firstTokenOfParam)) {
137
+ if (shouldHaveParens && !hasParens) {
169
138
  context.report({
170
139
  node,
171
- messageId: "unexpectedParens",
172
- loc: getLocation(node),
173
- fix: fixParamsWithParenthesis
140
+ messageId: requireForBlockBody ? "expectedParensBlock" : "expectedParens",
141
+ loc: param.loc,
142
+ *fix(fixer) {
143
+ yield fixer.insertTextBefore(param, "(");
144
+ yield fixer.insertTextAfter(param, ")");
145
+ }
174
146
  });
175
147
  }
176
- return;
177
- }
178
148
 
179
- if (firstTokenOfParam.type === "Identifier") {
180
- const after = sourceCode.getTokenAfter(firstTokenOfParam);
181
-
182
- // (x) => x
183
- if (after.value !== ")") {
149
+ if (
150
+ !shouldHaveParens &&
151
+ hasParens &&
152
+ param.type === "Identifier" &&
153
+ !param.typeAnnotation &&
154
+ !node.returnType &&
155
+ !hasCommentsInParensOfParams(node, openingParen) &&
156
+ !hasUnexpectedTokensBeforeOpeningParen(node, openingParen)
157
+ ) {
184
158
  context.report({
185
159
  node,
186
- messageId: "expectedParens",
187
- loc: getLocation(node),
188
- fix(fixer) {
189
- return fixer.replaceText(firstTokenOfParam, `(${firstTokenOfParam.value})`);
160
+ messageId: requireForBlockBody ? "unexpectedParensInline" : "unexpectedParens",
161
+ loc: param.loc,
162
+ *fix(fixer) {
163
+ const tokenBeforeOpeningParen = sourceCode.getTokenBefore(openingParen);
164
+ const closingParen = getClosingParenOfParams(node);
165
+
166
+ if (
167
+ tokenBeforeOpeningParen &&
168
+ tokenBeforeOpeningParen.range[1] === openingParen.range[0] &&
169
+ !astUtils.canTokensBeAdjacent(tokenBeforeOpeningParen, sourceCode.getFirstToken(param))
170
+ ) {
171
+ yield fixer.insertTextBefore(openingParen, " ");
172
+ }
173
+
174
+ // remove parens, whitespace inside parens, and possible trailing comma
175
+ yield fixer.removeRange([openingParen.range[0], param.range[0]]);
176
+ yield fixer.removeRange([param.range[1], closingParen.range[1]]);
190
177
  }
191
178
  });
192
179
  }
193
180
  }
194
- }
195
-
196
- return {
197
- "ArrowFunctionExpression[params.length=1]": parens
198
181
  };
199
182
  }
200
183
  };
@@ -32,6 +32,10 @@ module.exports = {
32
32
  type: "boolean",
33
33
  default: false
34
34
  },
35
+ ignoreGlobals: {
36
+ type: "boolean",
37
+ default: false
38
+ },
35
39
  properties: {
36
40
  enum: ["always", "never"]
37
41
  },
@@ -61,8 +65,11 @@ module.exports = {
61
65
  let properties = options.properties || "";
62
66
  const ignoreDestructuring = options.ignoreDestructuring;
63
67
  const ignoreImports = options.ignoreImports;
68
+ const ignoreGlobals = options.ignoreGlobals;
64
69
  const allow = options.allow || [];
65
70
 
71
+ let globalScope;
72
+
66
73
  if (properties !== "always" && properties !== "never") {
67
74
  properties = "always";
68
75
  }
@@ -159,6 +166,37 @@ module.exports = {
159
166
  return false;
160
167
  }
161
168
 
169
+ /**
170
+ * Checks whether the given node represents a reference to a global variable that is not declared in the source code.
171
+ * These identifiers will be allowed, as it is assumed that user has no control over the names of external global variables.
172
+ * @param {ASTNode} node `Identifier` node to check.
173
+ * @returns {boolean} `true` if the node is a reference to a global variable.
174
+ */
175
+ function isReferenceToGlobalVariable(node) {
176
+ const variable = globalScope.set.get(node.name);
177
+
178
+ return variable && variable.defs.length === 0 &&
179
+ variable.references.some(ref => ref.identifier === node);
180
+ }
181
+
182
+ /**
183
+ * Checks whether the given node represents a reference to a property of an object in an object literal expression.
184
+ * This allows to differentiate between a global variable that is allowed to be used as a reference, and the key
185
+ * of the expressed object (which shouldn't be allowed).
186
+ * @param {ASTNode} node `Identifier` node to check.
187
+ * @returns {boolean} `true` if the node is a property name of an object literal expression
188
+ */
189
+ function isPropertyNameInObjectLiteral(node) {
190
+ const parent = node.parent;
191
+
192
+ return (
193
+ parent.type === "Property" &&
194
+ parent.parent.type === "ObjectExpression" &&
195
+ !parent.computed &&
196
+ parent.key === node
197
+ );
198
+ }
199
+
162
200
  /**
163
201
  * Reports an AST node as a rule violation.
164
202
  * @param {ASTNode} node The node to report.
@@ -174,6 +212,10 @@ module.exports = {
174
212
 
175
213
  return {
176
214
 
215
+ Program() {
216
+ globalScope = context.getScope();
217
+ },
218
+
177
219
  Identifier(node) {
178
220
 
179
221
  /*
@@ -189,6 +231,11 @@ module.exports = {
189
231
  return;
190
232
  }
191
233
 
234
+ // Check if it's a global variable
235
+ if (ignoreGlobals && isReferenceToGlobalVariable(node) && !isPropertyNameInObjectLiteral(node)) {
236
+ return;
237
+ }
238
+
192
239
  // MemberExpressions get special rules
193
240
  if (node.parent.type === "MemberExpression") {
194
241
 
@@ -124,7 +124,8 @@ module.exports = {
124
124
  }
125
125
  ]
126
126
  }
127
- ]
127
+ ],
128
+ additionalItems: false
128
129
  },
129
130
 
130
131
  messages: {
@@ -457,11 +457,18 @@ module.exports = {
457
457
 
458
458
  return {
459
459
  IfStatement(node) {
460
- if (node.parent.type !== "IfStatement") {
460
+ const parent = node.parent;
461
+ const isElseIf = parent.type === "IfStatement" && parent.alternate === node;
462
+
463
+ if (!isElseIf) {
464
+
465
+ // This is a top `if`, check the whole `if-else-if` chain
461
466
  prepareIfChecks(node).forEach(preparedCheck => {
462
467
  preparedCheck.check();
463
468
  });
464
469
  }
470
+
471
+ // Skip `else if`, it's already checked (when the top `if` was visited)
465
472
  },
466
473
 
467
474
  WhileStatement(node) {
@@ -116,7 +116,13 @@ module.exports = {
116
116
  if (never && hasWhitespace) {
117
117
  context.report({
118
118
  node,
119
- loc: leftToken.loc.start,
119
+ loc: {
120
+ start: leftToken.loc.end,
121
+ end: {
122
+ line: rightToken.loc.start.line,
123
+ column: rightToken.loc.start.column - 1
124
+ }
125
+ },
120
126
  messageId: "unexpectedWhitespace",
121
127
  fix(fixer) {
122
128
 
@@ -134,7 +140,13 @@ module.exports = {
134
140
  } else if (!never && !hasWhitespace) {
135
141
  context.report({
136
142
  node,
137
- loc: leftToken.loc.start,
143
+ loc: {
144
+ start: {
145
+ line: leftToken.loc.end.line,
146
+ column: leftToken.loc.end.column - 1
147
+ },
148
+ end: rightToken.loc.start
149
+ },
138
150
  messageId: "missing",
139
151
  fix(fixer) {
140
152
  return fixer.insertTextBefore(rightToken, " ");
@@ -143,7 +155,10 @@ module.exports = {
143
155
  } else if (!never && !allowNewlines && hasNewline) {
144
156
  context.report({
145
157
  node,
146
- loc: leftToken.loc.start,
158
+ loc: {
159
+ start: leftToken.loc.end,
160
+ end: rightToken.loc.start
161
+ },
147
162
  messageId: "unexpectedNewline",
148
163
  fix(fixer) {
149
164
  return fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " ");
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview Rule that warns when identifier names that are
3
- * blacklisted in the configuration are used.
3
+ * specified in the configuration are used.
4
4
  * @author Keith Cirkel (http://keithcirkel.co.uk)
5
5
  */
6
6
 
@@ -117,7 +117,7 @@ module.exports = {
117
117
  description: "disallow specified identifiers",
118
118
  category: "Stylistic Issues",
119
119
  recommended: false,
120
- url: "https://eslint.org/docs/rules/id-blacklist"
120
+ url: "https://eslint.org/docs/rules/id-denylist"
121
121
  },
122
122
 
123
123
  schema: {
@@ -128,25 +128,25 @@ module.exports = {
128
128
  uniqueItems: true
129
129
  },
130
130
  messages: {
131
- blacklisted: "Identifier '{{name}}' is blacklisted."
131
+ restricted: "Identifier '{{name}}' is restricted."
132
132
  }
133
133
  },
134
134
 
135
135
  create(context) {
136
136
 
137
- const blacklist = new Set(context.options);
137
+ const denyList = new Set(context.options);
138
138
  const reportedNodes = new Set();
139
139
 
140
140
  let globalScope;
141
141
 
142
142
  /**
143
- * Checks whether the given name is blacklisted.
143
+ * Checks whether the given name is restricted.
144
144
  * @param {string} name The name to check.
145
- * @returns {boolean} `true` if the name is blacklisted.
145
+ * @returns {boolean} `true` if the name is restricted.
146
146
  * @private
147
147
  */
148
- function isBlacklisted(name) {
149
- return blacklist.has(name);
148
+ function isRestricted(name) {
149
+ return denyList.has(name);
150
150
  }
151
151
 
152
152
  /**
@@ -172,8 +172,8 @@ module.exports = {
172
172
 
173
173
  /*
174
174
  * Member access has special rules for checking property names.
175
- * Read access to a property with a blacklisted name is allowed, because it can be on an object that user has no control over.
176
- * Write access isn't allowed, because it potentially creates a new property with a blacklisted name.
175
+ * Read access to a property with a restricted name is allowed, because it can be on an object that user has no control over.
176
+ * Write access isn't allowed, because it potentially creates a new property with a restricted name.
177
177
  */
178
178
  if (
179
179
  parent.type === "MemberExpression" &&
@@ -205,7 +205,7 @@ module.exports = {
205
205
  if (!reportedNodes.has(node)) {
206
206
  context.report({
207
207
  node,
208
- messageId: "blacklisted",
208
+ messageId: "restricted",
209
209
  data: {
210
210
  name: node.name
211
211
  }
@@ -221,7 +221,7 @@ module.exports = {
221
221
  },
222
222
 
223
223
  Identifier(node) {
224
- if (isBlacklisted(node.name) && shouldCheck(node)) {
224
+ if (isRestricted(node.name) && shouldCheck(node)) {
225
225
  report(node);
226
226
  }
227
227
  }
@@ -39,7 +39,8 @@ module.exports = {
39
39
  type: "boolean",
40
40
  default: false
41
41
  }
42
- }
42
+ },
43
+ additionalProperties: false
43
44
  }
44
45
  ],
45
46
  messages: {
@@ -56,7 +56,10 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
56
56
  "grouped-accessor-pairs": () => require("./grouped-accessor-pairs"),
57
57
  "guard-for-in": () => require("./guard-for-in"),
58
58
  "handle-callback-err": () => require("./handle-callback-err"),
59
- "id-blacklist": () => require("./id-blacklist"),
59
+
60
+ // Renamed to id-denylist.
61
+ "id-blacklist": () => require("./id-denylist"),
62
+ "id-denylist": () => require("./id-denylist"),
60
63
  "id-length": () => require("./id-length"),
61
64
  "id-match": () => require("./id-match"),
62
65
  "implicit-arrow-linebreak": () => require("./implicit-arrow-linebreak"),
@@ -176,6 +179,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
176
179
  "no-plusplus": () => require("./no-plusplus"),
177
180
  "no-process-env": () => require("./no-process-env"),
178
181
  "no-process-exit": () => require("./no-process-exit"),
182
+ "no-promise-executor-return": () => require("./no-promise-executor-return"),
179
183
  "no-proto": () => require("./no-proto"),
180
184
  "no-prototype-builtins": () => require("./no-prototype-builtins"),
181
185
  "no-redeclare": () => require("./no-redeclare"),
@@ -212,6 +216,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
212
216
  "no-unmodified-loop-condition": () => require("./no-unmodified-loop-condition"),
213
217
  "no-unneeded-ternary": () => require("./no-unneeded-ternary"),
214
218
  "no-unreachable": () => require("./no-unreachable"),
219
+ "no-unreachable-loop": () => require("./no-unreachable-loop"),
215
220
  "no-unsafe-finally": () => require("./no-unsafe-finally"),
216
221
  "no-unsafe-negation": () => require("./no-unsafe-negation"),
217
222
  "no-unused-expressions": () => require("./no-unused-expressions"),
@@ -433,11 +433,15 @@ module.exports = {
433
433
  tokenBeforeColon = sourceCode.getTokenBefore(nextColon, { includeComments: true }),
434
434
  tokenAfterColon = sourceCode.getTokenAfter(nextColon, { includeComments: true }),
435
435
  isKeySide = side === "key",
436
- locStart = isKeySide ? tokenBeforeColon.loc.start : tokenAfterColon.loc.start,
437
436
  isExtra = diff > 0,
438
437
  diffAbs = Math.abs(diff),
439
438
  spaces = Array(diffAbs + 1).join(" ");
440
439
 
440
+ const locStart = isKeySide ? tokenBeforeColon.loc.end : nextColon.loc.start;
441
+ const locEnd = isKeySide ? nextColon.loc.start : tokenAfterColon.loc.start;
442
+ const missingLoc = isKeySide ? tokenBeforeColon.loc : tokenAfterColon.loc;
443
+ const loc = isExtra ? { start: locStart, end: locEnd } : missingLoc;
444
+
441
445
  if ((
442
446
  diff && mode === "strict" ||
443
447
  diff < 0 && mode === "minimum" ||
@@ -482,7 +486,7 @@ module.exports = {
482
486
 
483
487
  context.report({
484
488
  node: property[side],
485
- loc: locStart,
489
+ loc,
486
490
  messageId,
487
491
  data: {
488
492
  computed: property.computed ? "computed " : "",