eslint 6.3.0 → 6.6.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 (189) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/README.md +11 -10
  3. package/bin/eslint.js +38 -12
  4. package/lib/cli-engine/cascading-config-array-factory.js +2 -1
  5. package/lib/cli-engine/cli-engine.js +11 -11
  6. package/lib/cli-engine/config-array/config-array.js +0 -4
  7. package/lib/cli-engine/config-array/config-dependency.js +2 -0
  8. package/lib/cli-engine/config-array/override-tester.js +4 -2
  9. package/lib/cli-engine/config-array-factory.js +7 -1
  10. package/lib/cli-engine/file-enumerator.js +5 -3
  11. package/lib/cli-engine/formatters/html.js +1 -0
  12. package/lib/cli-engine/ignored-paths.js +4 -3
  13. package/lib/cli-engine/lint-result-cache.js +0 -1
  14. package/lib/cli.js +13 -12
  15. package/lib/init/autoconfig.js +1 -11
  16. package/lib/init/config-file.js +0 -1
  17. package/lib/init/config-initializer.js +0 -1
  18. package/lib/init/config-rule.js +3 -7
  19. package/lib/init/npm-utils.js +1 -6
  20. package/lib/linter/code-path-analysis/code-path-analyzer.js +24 -38
  21. package/lib/linter/code-path-analysis/code-path-segment.js +17 -25
  22. package/lib/linter/code-path-analysis/code-path-state.js +40 -81
  23. package/lib/linter/code-path-analysis/code-path.js +10 -11
  24. package/lib/linter/code-path-analysis/debug-helpers.js +9 -13
  25. package/lib/linter/code-path-analysis/fork-context.js +23 -34
  26. package/lib/linter/code-path-analysis/id-generator.js +2 -2
  27. package/lib/linter/linter.js +121 -96
  28. package/lib/linter/node-event-generator.js +3 -2
  29. package/lib/options.js +6 -0
  30. package/lib/rule-tester/rule-tester.js +7 -10
  31. package/lib/rules/accessor-pairs.js +59 -19
  32. package/lib/rules/array-bracket-newline.js +12 -15
  33. package/lib/rules/array-bracket-spacing.js +12 -12
  34. package/lib/rules/array-callback-return.js +6 -11
  35. package/lib/rules/array-element-newline.js +5 -8
  36. package/lib/rules/arrow-parens.js +0 -1
  37. package/lib/rules/block-scoped-var.js +3 -3
  38. package/lib/rules/block-spacing.js +4 -4
  39. package/lib/rules/capitalized-comments.js +2 -9
  40. package/lib/rules/class-methods-use-this.js +3 -3
  41. package/lib/rules/comma-dangle.js +15 -23
  42. package/lib/rules/comma-spacing.js +1 -1
  43. package/lib/rules/computed-property-spacing.js +28 -11
  44. package/lib/rules/consistent-return.js +4 -5
  45. package/lib/rules/consistent-this.js +5 -5
  46. package/lib/rules/constructor-super.js +14 -16
  47. package/lib/rules/curly.js +3 -5
  48. package/lib/rules/default-param-last.js +62 -0
  49. package/lib/rules/dot-location.js +11 -12
  50. package/lib/rules/eqeqeq.js +7 -19
  51. package/lib/rules/func-names.js +6 -6
  52. package/lib/rules/function-call-argument-newline.js +5 -5
  53. package/lib/rules/generator-star-spacing.js +4 -9
  54. package/lib/rules/getter-return.js +4 -7
  55. package/lib/rules/indent-legacy.js +1 -1
  56. package/lib/rules/indent.js +46 -8
  57. package/lib/rules/index.js +3 -0
  58. package/lib/rules/init-declarations.js +2 -2
  59. package/lib/rules/jsx-quotes.js +1 -1
  60. package/lib/rules/keyword-spacing.js +32 -56
  61. package/lib/rules/lines-around-directive.js +1 -1
  62. package/lib/rules/max-len.js +0 -5
  63. package/lib/rules/max-statements-per-line.js +3 -7
  64. package/lib/rules/multiline-ternary.js +3 -3
  65. package/lib/rules/new-parens.js +5 -1
  66. package/lib/rules/newline-after-var.js +6 -7
  67. package/lib/rules/newline-before-return.js +8 -9
  68. package/lib/rules/newline-per-chained-call.js +2 -4
  69. package/lib/rules/no-class-assign.js +2 -2
  70. package/lib/rules/no-compare-neg-zero.js +1 -2
  71. package/lib/rules/no-confusing-arrow.js +2 -2
  72. package/lib/rules/no-console.js +4 -8
  73. package/lib/rules/no-const-assign.js +1 -1
  74. package/lib/rules/no-dupe-args.js +1 -1
  75. package/lib/rules/no-dupe-class-members.js +3 -4
  76. package/lib/rules/no-dupe-keys.js +6 -5
  77. package/lib/rules/no-duplicate-imports.js +14 -18
  78. package/lib/rules/no-else-return.js +0 -8
  79. package/lib/rules/no-empty-function.js +2 -4
  80. package/lib/rules/no-eval.js +10 -18
  81. package/lib/rules/no-ex-assign.js +1 -1
  82. package/lib/rules/no-extra-bind.js +12 -13
  83. package/lib/rules/no-extra-boolean-cast.js +1 -3
  84. package/lib/rules/no-extra-label.js +13 -10
  85. package/lib/rules/no-extra-parens.js +32 -17
  86. package/lib/rules/no-extra-semi.js +5 -6
  87. package/lib/rules/no-fallthrough.js +6 -6
  88. package/lib/rules/no-func-assign.js +3 -3
  89. package/lib/rules/no-global-assign.js +4 -4
  90. package/lib/rules/no-implicit-coercion.js +10 -10
  91. package/lib/rules/no-implied-eval.js +0 -1
  92. package/lib/rules/no-import-assign.js +238 -0
  93. package/lib/rules/no-invalid-this.js +1 -3
  94. package/lib/rules/no-labels.js +3 -6
  95. package/lib/rules/no-lone-blocks.js +7 -2
  96. package/lib/rules/no-loop-func.js +6 -11
  97. package/lib/rules/no-magic-numbers.js +6 -6
  98. package/lib/rules/no-misleading-character-class.js +14 -7
  99. package/lib/rules/no-mixed-operators.js +13 -22
  100. package/lib/rules/no-mixed-requires.js +0 -1
  101. package/lib/rules/no-multi-spaces.js +1 -1
  102. package/lib/rules/no-native-reassign.js +4 -4
  103. package/lib/rules/no-obj-calls.js +29 -9
  104. package/lib/rules/no-octal-escape.js +14 -8
  105. package/lib/rules/no-param-reassign.js +28 -7
  106. package/lib/rules/no-redeclare.js +1 -1
  107. package/lib/rules/no-regex-spaces.js +105 -45
  108. package/lib/rules/no-restricted-imports.js +11 -11
  109. package/lib/rules/no-self-assign.js +18 -18
  110. package/lib/rules/no-sequences.js +5 -5
  111. package/lib/rules/no-shadow.js +1 -4
  112. package/lib/rules/no-tabs.js +8 -2
  113. package/lib/rules/no-this-before-super.js +12 -13
  114. package/lib/rules/no-trailing-spaces.js +19 -7
  115. package/lib/rules/no-undef-init.js +7 -1
  116. package/lib/rules/no-unmodified-loop-condition.js +16 -29
  117. package/lib/rules/no-unneeded-ternary.js +3 -3
  118. package/lib/rules/no-unreachable.js +7 -7
  119. package/lib/rules/no-unsafe-finally.js +4 -7
  120. package/lib/rules/no-unsafe-negation.js +34 -19
  121. package/lib/rules/no-unused-expressions.js +11 -7
  122. package/lib/rules/no-unused-labels.js +3 -6
  123. package/lib/rules/no-unused-vars.js +22 -29
  124. package/lib/rules/no-use-before-define.js +10 -15
  125. package/lib/rules/no-useless-call.js +4 -4
  126. package/lib/rules/no-useless-concat.js +4 -4
  127. package/lib/rules/no-useless-constructor.js +14 -22
  128. package/lib/rules/no-useless-escape.js +3 -5
  129. package/lib/rules/no-useless-rename.js +32 -20
  130. package/lib/rules/no-useless-return.js +11 -17
  131. package/lib/rules/no-var.js +12 -25
  132. package/lib/rules/no-warning-comments.js +0 -1
  133. package/lib/rules/no-whitespace-before-property.js +3 -3
  134. package/lib/rules/object-curly-newline.js +7 -10
  135. package/lib/rules/object-curly-spacing.js +14 -15
  136. package/lib/rules/object-shorthand.js +36 -10
  137. package/lib/rules/one-var-declaration-per-line.js +2 -2
  138. package/lib/rules/operator-assignment.js +22 -1
  139. package/lib/rules/padded-blocks.js +1 -1
  140. package/lib/rules/padding-line-between-statements.js +0 -16
  141. package/lib/rules/prefer-arrow-callback.js +6 -6
  142. package/lib/rules/prefer-const.js +13 -21
  143. package/lib/rules/prefer-destructuring.js +1 -7
  144. package/lib/rules/prefer-named-capture-group.js +3 -16
  145. package/lib/rules/prefer-numeric-literals.js +35 -3
  146. package/lib/rules/prefer-object-spread.js +7 -7
  147. package/lib/rules/prefer-regex-literals.js +125 -0
  148. package/lib/rules/prefer-rest-params.js +3 -6
  149. package/lib/rules/prefer-spread.js +4 -4
  150. package/lib/rules/prefer-template.js +5 -6
  151. package/lib/rules/quote-props.js +1 -1
  152. package/lib/rules/quotes.js +11 -6
  153. package/lib/rules/radix.js +5 -10
  154. package/lib/rules/require-await.js +2 -5
  155. package/lib/rules/require-yield.js +2 -2
  156. package/lib/rules/rest-spread-spacing.js +1 -1
  157. package/lib/rules/sort-imports.js +3 -4
  158. package/lib/rules/sort-keys.js +1 -3
  159. package/lib/rules/space-before-blocks.js +1 -2
  160. package/lib/rules/space-before-function-paren.js +12 -1
  161. package/lib/rules/space-in-parens.js +81 -75
  162. package/lib/rules/space-infix-ops.js +5 -5
  163. package/lib/rules/spaced-comment.js +15 -18
  164. package/lib/rules/strict.js +2 -4
  165. package/lib/rules/symbol-description.js +1 -2
  166. package/lib/rules/template-curly-spacing.js +2 -2
  167. package/lib/rules/use-isnan.js +104 -6
  168. package/lib/rules/utils/ast-utils.js +53 -81
  169. package/lib/rules/utils/fix-tracker.js +0 -6
  170. package/lib/rules/utils/lazy-loading-rule-map.js +0 -1
  171. package/lib/rules/vars-on-top.js +11 -11
  172. package/lib/shared/config-ops.js +2 -2
  173. package/lib/shared/logging.js +2 -0
  174. package/lib/shared/runtime-info.js +163 -0
  175. package/lib/shared/traverser.js +2 -0
  176. package/lib/source-code/source-code.js +11 -12
  177. package/lib/source-code/token-store/backward-token-comment-cursor.js +5 -5
  178. package/lib/source-code/token-store/backward-token-cursor.js +5 -5
  179. package/lib/source-code/token-store/cursors.js +17 -19
  180. package/lib/source-code/token-store/decorative-cursor.js +1 -1
  181. package/lib/source-code/token-store/filter-cursor.js +2 -2
  182. package/lib/source-code/token-store/forward-token-comment-cursor.js +5 -5
  183. package/lib/source-code/token-store/forward-token-cursor.js +5 -5
  184. package/lib/source-code/token-store/index.js +86 -92
  185. package/lib/source-code/token-store/limit-cursor.js +2 -2
  186. package/lib/source-code/token-store/padded-token-cursor.js +7 -7
  187. package/lib/source-code/token-store/skip-cursor.js +2 -2
  188. package/lib/source-code/token-store/utils.js +9 -13
  189. package/package.json +8 -5
@@ -292,10 +292,15 @@ function getDirectiveComments(filename, ast, ruleMapper, warnInlineConfig) {
292
292
  if (!match) {
293
293
  return;
294
294
  }
295
- const lineCommentSupported = /^eslint-disable-(next-)?line$/u.test(match[1]);
295
+ const directiveText = match[1];
296
+ const lineCommentSupported = /^eslint-disable-(next-)?line$/u.test(directiveText);
296
297
 
297
- if (warnInlineConfig && (lineCommentSupported || comment.type === "Block")) {
298
- const kind = comment.type === "Block" ? `/*${match[1]}*/` : `//${match[1]}`;
298
+ if (comment.type === "Line" && !lineCommentSupported) {
299
+ return;
300
+ }
301
+
302
+ if (warnInlineConfig) {
303
+ const kind = comment.type === "Block" ? `/*${directiveText}*/` : `//${directiveText}`;
299
304
 
300
305
  problems.push(createLintingProblem({
301
306
  ruleId: null,
@@ -306,108 +311,101 @@ function getDirectiveComments(filename, ast, ruleMapper, warnInlineConfig) {
306
311
  return;
307
312
  }
308
313
 
309
- const directiveValue = trimmedCommentText.slice(match.index + match[1].length);
310
- let directiveType = "";
314
+ if (lineCommentSupported && comment.loc.start.line !== comment.loc.end.line) {
315
+ const message = `${directiveText} comment should not span multiple lines.`;
311
316
 
312
- if (lineCommentSupported) {
313
- if (comment.loc.start.line === comment.loc.end.line) {
314
- directiveType = match[1].slice("eslint-".length);
315
- } else {
316
- const message = `${match[1]} comment should not span multiple lines.`;
317
+ problems.push(createLintingProblem({
318
+ ruleId: null,
319
+ message,
320
+ loc: comment.loc
321
+ }));
322
+ return;
323
+ }
317
324
 
318
- problems.push(createLintingProblem({
319
- ruleId: null,
320
- message,
321
- loc: comment.loc
322
- }));
325
+ const directiveValue = trimmedCommentText.slice(match.index + directiveText.length);
326
+
327
+ switch (directiveText) {
328
+ case "eslint-disable":
329
+ case "eslint-enable":
330
+ case "eslint-disable-next-line":
331
+ case "eslint-disable-line": {
332
+ const directiveType = directiveText.slice("eslint-".length);
333
+ const options = { type: directiveType, loc: comment.loc, value: directiveValue, ruleMapper };
334
+ const { directives, directiveProblems } = createDisableDirectives(options);
335
+
336
+ disableDirectives.push(...directives);
337
+ problems.push(...directiveProblems);
338
+ break;
323
339
  }
324
- } else if (comment.type === "Block") {
325
- switch (match[1]) {
326
- case "exported":
327
- Object.assign(exportedVariables, commentParser.parseStringConfig(directiveValue, comment));
328
- break;
329
340
 
330
- case "globals":
331
- case "global":
332
- for (const [id, { value }] of Object.entries(commentParser.parseStringConfig(directiveValue, comment))) {
333
- let normalizedValue;
341
+ case "exported":
342
+ Object.assign(exportedVariables, commentParser.parseStringConfig(directiveValue, comment));
343
+ break;
344
+
345
+ case "globals":
346
+ case "global":
347
+ for (const [id, { value }] of Object.entries(commentParser.parseStringConfig(directiveValue, comment))) {
348
+ let normalizedValue;
349
+
350
+ try {
351
+ normalizedValue = ConfigOps.normalizeConfigGlobal(value);
352
+ } catch (err) {
353
+ problems.push(createLintingProblem({
354
+ ruleId: null,
355
+ loc: comment.loc,
356
+ message: err.message
357
+ }));
358
+ continue;
359
+ }
360
+
361
+ if (enabledGlobals[id]) {
362
+ enabledGlobals[id].comments.push(comment);
363
+ enabledGlobals[id].value = normalizedValue;
364
+ } else {
365
+ enabledGlobals[id] = {
366
+ comments: [comment],
367
+ value: normalizedValue
368
+ };
369
+ }
370
+ }
371
+ break;
372
+
373
+ case "eslint": {
374
+ const parseResult = commentParser.parseJsonConfig(directiveValue, comment.loc);
375
+
376
+ if (parseResult.success) {
377
+ Object.keys(parseResult.config).forEach(name => {
378
+ const rule = ruleMapper(name);
379
+ const ruleValue = parseResult.config[name];
380
+
381
+ if (rule === null) {
382
+ problems.push(createLintingProblem({ ruleId: name, loc: comment.loc }));
383
+ return;
384
+ }
334
385
 
335
386
  try {
336
- normalizedValue = ConfigOps.normalizeConfigGlobal(value);
387
+ validator.validateRuleOptions(rule, name, ruleValue);
337
388
  } catch (err) {
338
389
  problems.push(createLintingProblem({
339
- ruleId: null,
340
- loc: comment.loc,
341
- message: err.message
390
+ ruleId: name,
391
+ message: err.message,
392
+ loc: comment.loc
342
393
  }));
343
- continue;
344
- }
345
394
 
346
- if (enabledGlobals[id]) {
347
- enabledGlobals[id].comments.push(comment);
348
- enabledGlobals[id].value = normalizedValue;
349
- } else {
350
- enabledGlobals[id] = {
351
- comments: [comment],
352
- value: normalizedValue
353
- };
395
+ // do not apply the config, if found invalid options.
396
+ return;
354
397
  }
355
- }
356
- break;
357
-
358
- case "eslint-disable":
359
- directiveType = "disable";
360
- break;
361
-
362
- case "eslint-enable":
363
- directiveType = "enable";
364
- break;
365
-
366
- case "eslint": {
367
- const parseResult = commentParser.parseJsonConfig(directiveValue, comment.loc);
368
-
369
- if (parseResult.success) {
370
- Object.keys(parseResult.config).forEach(name => {
371
- const rule = ruleMapper(name);
372
- const ruleValue = parseResult.config[name];
373
-
374
- if (rule === null) {
375
- problems.push(createLintingProblem({ ruleId: name, loc: comment.loc }));
376
- return;
377
- }
378
-
379
- try {
380
- validator.validateRuleOptions(rule, name, ruleValue);
381
- } catch (err) {
382
- problems.push(createLintingProblem({
383
- ruleId: name,
384
- message: err.message,
385
- loc: comment.loc
386
- }));
387
-
388
- // do not apply the config, if found invalid options.
389
- return;
390
- }
391
-
392
- configuredRules[name] = ruleValue;
393
- });
394
- } else {
395
- problems.push(parseResult.error);
396
- }
397
398
 
398
- break;
399
+ configuredRules[name] = ruleValue;
400
+ });
401
+ } else {
402
+ problems.push(parseResult.error);
399
403
  }
400
404
 
401
- // no default
405
+ break;
402
406
  }
403
- }
404
-
405
- if (directiveType !== "") {
406
- const options = { type: directiveType, loc: comment.loc, value: directiveValue, ruleMapper };
407
- const { directives, directiveProblems } = createDisableDirectives(options);
408
407
 
409
- disableDirectives.push(...directives);
410
- problems.push(...directiveProblems);
408
+ // no default
411
409
  }
412
410
  });
413
411
 
@@ -438,7 +436,7 @@ const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)\*\//gu;
438
436
 
439
437
  /**
440
438
  * Checks whether or not there is a comment which has "eslint-env *" in a given text.
441
- * @param {string} text - A source code text to check.
439
+ * @param {string} text A source code text to check.
442
440
  * @returns {Object|null} A result of parseListConfig() with "eslint-env *" comment.
443
441
  */
444
442
  function findEslintEnv(text) {
@@ -472,7 +470,6 @@ function normalizeFilename(filename) {
472
470
  return index === -1 ? filename : parts.slice(index).join(path.sep);
473
471
  }
474
472
 
475
- // eslint-disable-next-line valid-jsdoc
476
473
  /**
477
474
  * Normalizes the possible options for `linter.verify` and `linter.verifyAndFix` to a
478
475
  * consistent shape.
@@ -556,8 +553,7 @@ function resolveGlobals(providedGlobals, enabledEnvironments) {
556
553
 
557
554
  /**
558
555
  * Strips Unicode BOM from a given text.
559
- *
560
- * @param {string} text - A text to strip.
556
+ * @param {string} text A text to strip.
561
557
  * @returns {string} The stripped text.
562
558
  */
563
559
  function stripUnicodeBOM(text) {
@@ -670,6 +666,8 @@ function parse(text, parser, providedParserOptions, filePath) {
670
666
  // If the message includes a leading line number, strip it:
671
667
  const message = `Parsing error: ${ex.message.replace(/^line \d+:/iu, "").trim()}`;
672
668
 
669
+ debug("%s\n%s", message, ex.stack);
670
+
673
671
  return {
674
672
  success: false,
675
673
  error: {
@@ -814,9 +812,10 @@ const BASE_TRAVERSAL_CONTEXT = Object.freeze(
814
812
  * @param {Object} settings The settings that were enabled in the config
815
813
  * @param {string} filename The reported filename of the code
816
814
  * @param {boolean} disableFixes If true, it doesn't make `fix` properties.
815
+ * @param {string | undefined} cwd cwd of the cli
817
816
  * @returns {Problem[]} An array of reported problems
818
817
  */
819
- function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parserName, settings, filename, disableFixes) {
818
+ function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parserName, settings, filename, disableFixes, cwd) {
820
819
  const emitter = createEmitter();
821
820
  const nodeQueue = [];
822
821
  let currentNode = sourceCode.ast;
@@ -843,6 +842,7 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserOptions, parser
843
842
  {
844
843
  getAncestors: () => getAncestors(currentNode),
845
844
  getDeclaredVariables: sourceCode.scopeManager.getDeclaredVariables.bind(sourceCode.scopeManager),
845
+ getCwd: () => cwd,
846
846
  getFilename: () => filename,
847
847
  getScope: () => getScope(sourceCode.scopeManager, currentNode),
848
848
  getSourceCode: () => sourceCode,
@@ -989,6 +989,24 @@ function getRule(slots, ruleId) {
989
989
  );
990
990
  }
991
991
 
992
+ /**
993
+ * Normalize the value of the cwd
994
+ * @param {string | undefined} cwd raw value of the cwd, path to a directory that should be considered as the current working directory, can be undefined.
995
+ * @returns {string | undefined} normalized cwd
996
+ */
997
+ function normalizeCwd(cwd) {
998
+ if (cwd) {
999
+ return cwd;
1000
+ }
1001
+ if (typeof process === "object") {
1002
+ return process.cwd();
1003
+ }
1004
+
1005
+ // It's more explicit to assign the undefined
1006
+ // eslint-disable-next-line no-undefined
1007
+ return undefined;
1008
+ }
1009
+
992
1010
  /**
993
1011
  * The map to store private data.
994
1012
  * @type {WeakMap<Linter, LinterInternalSlots>}
@@ -1005,8 +1023,14 @@ const internalSlotsMap = new WeakMap();
1005
1023
  */
1006
1024
  class Linter {
1007
1025
 
1008
- constructor() {
1026
+ /**
1027
+ * Initialize the Linter.
1028
+ * @param {Object} [config] the config object
1029
+ * @param {string} [config.cwd] path to a directory that should be considered as the current working directory, can be undefined.
1030
+ */
1031
+ constructor({ cwd } = {}) {
1009
1032
  internalSlotsMap.set(this, {
1033
+ cwd: normalizeCwd(cwd),
1010
1034
  lastConfigArray: null,
1011
1035
  lastSourceCode: null,
1012
1036
  parserMap: new Map([["espree", espree]]),
@@ -1138,7 +1162,8 @@ class Linter {
1138
1162
  parserName,
1139
1163
  settings,
1140
1164
  options.filename,
1141
- options.disableFixes
1165
+ options.disableFixes,
1166
+ slots.cwd
1142
1167
  );
1143
1168
  } catch (err) {
1144
1169
  err.message += `\nOccurred while linting ${options.filename}`;
@@ -202,6 +202,7 @@ const parseSelector = lodash.memoize(rawSelector => {
202
202
  */
203
203
  class NodeEventGenerator {
204
204
 
205
+ // eslint-disable-next-line jsdoc/require-description
205
206
  /**
206
207
  * @param {SafeEmitter} emitter
207
208
  * An SafeEmitter which is the destination of events. This emitter must already
@@ -286,7 +287,7 @@ class NodeEventGenerator {
286
287
 
287
288
  /**
288
289
  * Emits an event of entering AST node.
289
- * @param {ASTNode} node - A node which was entered.
290
+ * @param {ASTNode} node A node which was entered.
290
291
  * @returns {void}
291
292
  */
292
293
  enterNode(node) {
@@ -298,7 +299,7 @@ class NodeEventGenerator {
298
299
 
299
300
  /**
300
301
  * Emits an event of leaving AST node.
301
- * @param {ASTNode} node - A node which was left.
302
+ * @param {ASTNode} node A node which was left.
302
303
  * @returns {void}
303
304
  */
304
305
  leaveNode(node) {
package/lib/options.js CHANGED
@@ -224,6 +224,12 @@ module.exports = optionator({
224
224
  default: "false",
225
225
  description: "Run config initialization wizard"
226
226
  },
227
+ {
228
+ option: "env-info",
229
+ type: "Boolean",
230
+ default: "false",
231
+ description: "Output execution environment information"
232
+ },
227
233
  {
228
234
  option: "debug",
229
235
  type: "Boolean",
@@ -78,8 +78,7 @@ const hasOwnProperty = Function.call.bind(Object.hasOwnProperty);
78
78
  /**
79
79
  * Clones a given value deeply.
80
80
  * Note: This ignores `parent` property.
81
- *
82
- * @param {any} x - A value to clone.
81
+ * @param {any} x A value to clone.
83
82
  * @returns {any} A cloned value.
84
83
  */
85
84
  function cloneDeeplyExcludesParent(x) {
@@ -104,8 +103,7 @@ function cloneDeeplyExcludesParent(x) {
104
103
 
105
104
  /**
106
105
  * Freezes a given value deeply.
107
- *
108
- * @param {any} x - A value to freeze.
106
+ * @param {any} x A value to freeze.
109
107
  * @returns {void}
110
108
  */
111
109
  function freezeDeeply(x) {
@@ -130,7 +128,7 @@ function freezeDeeply(x) {
130
128
  */
131
129
  function sanitize(text) {
132
130
  return text.replace(
133
- /[\u0000-\u001f]/gu, // eslint-disable-line no-control-regex
131
+ /[\u0000-\u0009|\u000b-\u001a]/gu, // eslint-disable-line no-control-regex
134
132
  c => `\\u${c.codePointAt(0).toString(16).padStart(4, "0")}`
135
133
  );
136
134
  }
@@ -146,8 +144,8 @@ const IT = Symbol("it");
146
144
  /**
147
145
  * This is `it` default handler if `it` don't exist.
148
146
  * @this {Mocha}
149
- * @param {string} text - The description of the test case.
150
- * @param {Function} method - The logic of the test case.
147
+ * @param {string} text The description of the test case.
148
+ * @param {Function} method The logic of the test case.
151
149
  * @returns {any} Returned value of `method`.
152
150
  */
153
151
  function itDefaultHandler(text, method) {
@@ -164,8 +162,8 @@ function itDefaultHandler(text, method) {
164
162
  /**
165
163
  * This is `describe` default handler if `describe` don't exist.
166
164
  * @this {Mocha}
167
- * @param {string} text - The description of the test case.
168
- * @param {Function} method - The logic of the test case.
165
+ * @param {string} text The description of the test case.
166
+ * @param {Function} method The logic of the test case.
169
167
  * @returns {any} Returned value of `method`.
170
168
  */
171
169
  function describeDefaultHandler(text, method) {
@@ -177,7 +175,6 @@ class RuleTester {
177
175
  /**
178
176
  * Creates a new instance of RuleTester.
179
177
  * @param {Object} [testerConfig] Optional, extra configuration for the tester
180
- * @constructor
181
178
  */
182
179
  constructor(testerConfig) {
183
180
 
@@ -79,7 +79,7 @@ function areEqualKeys(left, right) {
79
79
 
80
80
  /**
81
81
  * Checks whether or not a given node is of an accessor kind ('get' or 'set').
82
- * @param {ASTNode} node - A node to check.
82
+ * @param {ASTNode} node A node to check.
83
83
  * @returns {boolean} `true` if the node is of an accessor kind.
84
84
  */
85
85
  function isAccessorKind(node) {
@@ -88,8 +88,8 @@ function isAccessorKind(node) {
88
88
 
89
89
  /**
90
90
  * Checks whether or not a given node is an `Identifier` node which was named a given name.
91
- * @param {ASTNode} node - A node to check.
92
- * @param {string} name - An expected name of the node.
91
+ * @param {ASTNode} node A node to check.
92
+ * @param {string} name An expected name of the node.
93
93
  * @returns {boolean} `true` if the node is an `Identifier` node which was named as expected.
94
94
  */
95
95
  function isIdentifier(node, name) {
@@ -98,10 +98,10 @@ function isIdentifier(node, name) {
98
98
 
99
99
  /**
100
100
  * Checks whether or not a given node is an argument of a specified method call.
101
- * @param {ASTNode} node - A node to check.
102
- * @param {number} index - An expected index of the node in arguments.
103
- * @param {string} object - An expected name of the object of the method.
104
- * @param {string} property - An expected name of the method.
101
+ * @param {ASTNode} node A node to check.
102
+ * @param {number} index An expected index of the node in arguments.
103
+ * @param {string} object An expected name of the object of the method.
104
+ * @param {string} property An expected name of the method.
105
105
  * @returns {boolean} `true` if the node is an argument of the specified method call.
106
106
  */
107
107
  function isArgumentOfMethodCall(node, index, object, property) {
@@ -119,7 +119,7 @@ function isArgumentOfMethodCall(node, index, object, property) {
119
119
 
120
120
  /**
121
121
  * Checks whether or not a given node is a property descriptor.
122
- * @param {ASTNode} node - A node to check.
122
+ * @param {ASTNode} node A node to check.
123
123
  * @returns {boolean} `true` if the node is a property descriptor.
124
124
  */
125
125
  function isPropertyDescriptor(node) {
@@ -152,7 +152,7 @@ module.exports = {
152
152
  type: "suggestion",
153
153
 
154
154
  docs: {
155
- description: "enforce getter and setter pairs in objects",
155
+ description: "enforce getter and setter pairs in objects and classes",
156
156
  category: "Best Practices",
157
157
  recommended: false,
158
158
  url: "https://eslint.org/docs/rules/accessor-pairs"
@@ -168,6 +168,10 @@ module.exports = {
168
168
  setWithoutGet: {
169
169
  type: "boolean",
170
170
  default: true
171
+ },
172
+ enforceForClassMembers: {
173
+ type: "boolean",
174
+ default: false
171
175
  }
172
176
  },
173
177
  additionalProperties: false
@@ -177,13 +181,16 @@ module.exports = {
177
181
  missingGetterInPropertyDescriptor: "Getter is not present in property descriptor.",
178
182
  missingSetterInPropertyDescriptor: "Setter is not present in property descriptor.",
179
183
  missingGetterInObjectLiteral: "Getter is not present for {{ name }}.",
180
- missingSetterInObjectLiteral: "Setter is not present for {{ name }}."
184
+ missingSetterInObjectLiteral: "Setter is not present for {{ name }}.",
185
+ missingGetterInClass: "Getter is not present for class {{ name }}.",
186
+ missingSetterInClass: "Setter is not present for class {{ name }}."
181
187
  }
182
188
  },
183
189
  create(context) {
184
190
  const config = context.options[0] || {};
185
191
  const checkGetWithoutSet = config.getWithoutSet === true;
186
192
  const checkSetWithoutGet = config.setWithoutGet !== false;
193
+ const enforceForClassMembers = config.enforceForClassMembers === true;
187
194
  const sourceCode = context.getSourceCode();
188
195
 
189
196
  /**
@@ -201,6 +208,13 @@ module.exports = {
201
208
  loc: astUtils.getFunctionHeadLoc(node.value, sourceCode),
202
209
  data: { name: astUtils.getFunctionNameWithKind(node.value) }
203
210
  });
211
+ } else if (node.type === "MethodDefinition") {
212
+ context.report({
213
+ node,
214
+ messageId: `${messageKind}InClass`,
215
+ loc: astUtils.getFunctionHeadLoc(node.value, sourceCode),
216
+ data: { name: astUtils.getFunctionNameWithKind(node.value) }
217
+ });
204
218
  } else {
205
219
  context.report({
206
220
  node,
@@ -313,15 +327,41 @@ module.exports = {
313
327
  }
314
328
  }
315
329
 
316
- return {
317
- ObjectExpression(node) {
318
- if (checkSetWithoutGet || checkGetWithoutSet) {
319
- checkObjectLiteral(node);
320
- if (isPropertyDescriptor(node)) {
321
- checkPropertyDescriptor(node);
322
- }
323
- }
330
+ /**
331
+ * Checks the given object expression as an object literal and as a possible property descriptor.
332
+ * @param {ASTNode} node `ObjectExpression` node to check.
333
+ * @returns {void}
334
+ * @private
335
+ */
336
+ function checkObjectExpression(node) {
337
+ checkObjectLiteral(node);
338
+ if (isPropertyDescriptor(node)) {
339
+ checkPropertyDescriptor(node);
324
340
  }
325
- };
341
+ }
342
+
343
+ /**
344
+ * Checks the given class body.
345
+ * @param {ASTNode} node `ClassBody` node to check.
346
+ * @returns {void}
347
+ * @private
348
+ */
349
+ function checkClassBody(node) {
350
+ const methodDefinitions = node.body.filter(m => m.type === "MethodDefinition");
351
+
352
+ checkList(methodDefinitions.filter(m => m.static));
353
+ checkList(methodDefinitions.filter(m => !m.static));
354
+ }
355
+
356
+ const listeners = {};
357
+
358
+ if (checkSetWithoutGet || checkGetWithoutSet) {
359
+ listeners.ObjectExpression = checkObjectExpression;
360
+ if (enforceForClassMembers) {
361
+ listeners.ClassBody = checkClassBody;
362
+ }
363
+ }
364
+
365
+ return listeners;
326
366
  }
327
367
  };
@@ -65,8 +65,7 @@ module.exports = {
65
65
 
66
66
  /**
67
67
  * Normalizes a given option value.
68
- *
69
- * @param {string|Object|undefined} option - An option value to parse.
68
+ * @param {string|Object|undefined} option An option value to parse.
70
69
  * @returns {{multiline: boolean, minItems: number}} Normalized option object.
71
70
  */
72
71
  function normalizeOptionValue(option) {
@@ -97,8 +96,7 @@ module.exports = {
97
96
 
98
97
  /**
99
98
  * Normalizes a given option value.
100
- *
101
- * @param {string|Object|undefined} options - An option value to parse.
99
+ * @param {string|Object|undefined} options An option value to parse.
102
100
  * @returns {{ArrayExpression: {multiline: boolean, minItems: number}, ArrayPattern: {multiline: boolean, minItems: number}}} Normalized option object.
103
101
  */
104
102
  function normalizeOptions(options) {
@@ -109,8 +107,8 @@ module.exports = {
109
107
 
110
108
  /**
111
109
  * Reports that there shouldn't be a linebreak after the first token
112
- * @param {ASTNode} node - The node to report in the event of an error.
113
- * @param {Token} token - The token to use for the report.
110
+ * @param {ASTNode} node The node to report in the event of an error.
111
+ * @param {Token} token The token to use for the report.
114
112
  * @returns {void}
115
113
  */
116
114
  function reportNoBeginningLinebreak(node, token) {
@@ -132,8 +130,8 @@ module.exports = {
132
130
 
133
131
  /**
134
132
  * Reports that there shouldn't be a linebreak before the last token
135
- * @param {ASTNode} node - The node to report in the event of an error.
136
- * @param {Token} token - The token to use for the report.
133
+ * @param {ASTNode} node The node to report in the event of an error.
134
+ * @param {Token} token The token to use for the report.
137
135
  * @returns {void}
138
136
  */
139
137
  function reportNoEndingLinebreak(node, token) {
@@ -155,8 +153,8 @@ module.exports = {
155
153
 
156
154
  /**
157
155
  * Reports that there should be a linebreak after the first token
158
- * @param {ASTNode} node - The node to report in the event of an error.
159
- * @param {Token} token - The token to use for the report.
156
+ * @param {ASTNode} node The node to report in the event of an error.
157
+ * @param {Token} token The token to use for the report.
160
158
  * @returns {void}
161
159
  */
162
160
  function reportRequiredBeginningLinebreak(node, token) {
@@ -172,8 +170,8 @@ module.exports = {
172
170
 
173
171
  /**
174
172
  * Reports that there should be a linebreak before the last token
175
- * @param {ASTNode} node - The node to report in the event of an error.
176
- * @param {Token} token - The token to use for the report.
173
+ * @param {ASTNode} node The node to report in the event of an error.
174
+ * @param {Token} token The token to use for the report.
177
175
  * @returns {void}
178
176
  */
179
177
  function reportRequiredEndingLinebreak(node, token) {
@@ -189,8 +187,7 @@ module.exports = {
189
187
 
190
188
  /**
191
189
  * Reports a given node if it violated this rule.
192
- *
193
- * @param {ASTNode} node - A node to check. This is an ArrayExpression node or an ArrayPattern node.
190
+ * @param {ASTNode} node A node to check. This is an ArrayExpression node or an ArrayPattern node.
194
191
  * @returns {void}
195
192
  */
196
193
  function check(node) {
@@ -219,7 +216,7 @@ module.exports = {
219
216
  ) ||
220
217
  (
221
218
  options.consistent &&
222
- firstIncComment.loc.start.line !== openBracket.loc.end.line
219
+ openBracket.loc.end.line !== first.loc.start.line
223
220
  )
224
221
  );
225
222