eslint 8.56.0 → 9.0.0-alpha.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 (50) hide show
  1. package/README.md +2 -2
  2. package/conf/rule-type-list.json +3 -1
  3. package/lib/api.js +1 -1
  4. package/lib/cli-engine/cli-engine.js +13 -2
  5. package/lib/cli-engine/formatters/formatters-meta.json +1 -29
  6. package/lib/cli.js +32 -9
  7. package/lib/config/default-config.js +3 -0
  8. package/lib/config/flat-config-array.js +0 -20
  9. package/lib/config/flat-config-helpers.js +41 -20
  10. package/lib/config/flat-config-schema.js +35 -25
  11. package/lib/config/rule-validator.js +27 -4
  12. package/lib/eslint/eslint-helpers.js +32 -12
  13. package/lib/eslint/eslint.js +856 -373
  14. package/lib/eslint/index.js +2 -2
  15. package/lib/eslint/legacy-eslint.js +722 -0
  16. package/lib/linter/apply-disable-directives.js +33 -5
  17. package/lib/linter/config-comment-parser.js +1 -1
  18. package/lib/linter/linter.js +91 -96
  19. package/lib/linter/rules.js +6 -15
  20. package/lib/options.js +9 -1
  21. package/lib/rule-tester/rule-tester.js +240 -272
  22. package/lib/rules/index.js +0 -2
  23. package/lib/rules/no-constant-binary-expression.js +1 -1
  24. package/lib/rules/no-constructor-return.js +1 -1
  25. package/lib/rules/no-empty-static-block.js +1 -1
  26. package/lib/rules/no-extra-semi.js +1 -1
  27. package/lib/rules/no-implicit-coercion.js +17 -1
  28. package/lib/rules/no-inner-declarations.js +1 -1
  29. package/lib/rules/no-invalid-regexp.js +1 -1
  30. package/lib/rules/no-mixed-spaces-and-tabs.js +1 -1
  31. package/lib/rules/no-new-native-nonconstructor.js +1 -1
  32. package/lib/rules/no-new-symbol.js +8 -1
  33. package/lib/rules/no-sequences.js +1 -0
  34. package/lib/rules/no-unused-private-class-members.js +1 -1
  35. package/lib/shared/config-validator.js +44 -11
  36. package/lib/shared/types.js +1 -1
  37. package/lib/source-code/source-code.js +1 -79
  38. package/lib/unsupported-api.js +3 -5
  39. package/package.json +9 -11
  40. package/lib/cli-engine/formatters/checkstyle.js +0 -60
  41. package/lib/cli-engine/formatters/compact.js +0 -60
  42. package/lib/cli-engine/formatters/jslint-xml.js +0 -41
  43. package/lib/cli-engine/formatters/junit.js +0 -82
  44. package/lib/cli-engine/formatters/tap.js +0 -95
  45. package/lib/cli-engine/formatters/unix.js +0 -58
  46. package/lib/cli-engine/formatters/visualstudio.js +0 -63
  47. package/lib/eslint/flat-eslint.js +0 -1142
  48. package/lib/rule-tester/flat-rule-tester.js +0 -1122
  49. package/lib/rules/require-jsdoc.js +0 -122
  50. package/lib/rules/valid-jsdoc.js +0 -516
@@ -16,6 +16,11 @@
16
16
  //------------------------------------------------------------------------------
17
17
 
18
18
  const escapeRegExp = require("escape-string-regexp");
19
+ const {
20
+ Legacy: {
21
+ ConfigOps
22
+ }
23
+ } = require("@eslint/eslintrc/universal");
19
24
 
20
25
  /**
21
26
  * Compares the locations of two objects in a source file
@@ -345,11 +350,11 @@ function applyDirectives(options) {
345
350
  }
346
351
 
347
352
  const unusedDisableDirectivesToReport = options.directives
348
- .filter(directive => directive.type === "disable" && !usedDisableDirectives.has(directive));
353
+ .filter(directive => directive.type === "disable" && !usedDisableDirectives.has(directive) && !options.rulesToIgnore.has(directive.ruleId));
349
354
 
350
355
 
351
356
  const unusedEnableDirectivesToReport = new Set(
352
- options.directives.filter(directive => directive.unprocessedDirective.type === "enable")
357
+ options.directives.filter(directive => directive.unprocessedDirective.type === "enable" && !options.rulesToIgnore.has(directive.ruleId))
353
358
  );
354
359
 
355
360
  /*
@@ -410,11 +415,13 @@ function applyDirectives(options) {
410
415
  * @param {{ruleId: (string|null), line: number, column: number}[]} options.problems
411
416
  * A list of problems reported by rules, sorted by increasing location in the file, with one-based columns.
412
417
  * @param {"off" | "warn" | "error"} options.reportUnusedDisableDirectives If `"warn"` or `"error"`, adds additional problems for unused directives
418
+ * @param {Object} options.configuredRules The rules configuration.
419
+ * @param {Function} options.ruleFilter A predicate function to filter which rules should be executed.
413
420
  * @param {boolean} options.disableFixes If true, it doesn't make `fix` properties.
414
421
  * @returns {{ruleId: (string|null), line: number, column: number, suppressions?: {kind: string, justification: string}}[]}
415
422
  * An object with a list of reported problems, the suppressed of which contain the suppression information.
416
423
  */
417
- module.exports = ({ directives, disableFixes, problems, reportUnusedDisableDirectives = "off" }) => {
424
+ module.exports = ({ directives, disableFixes, problems, configuredRules, ruleFilter, reportUnusedDisableDirectives = "off" }) => {
418
425
  const blockDirectives = directives
419
426
  .filter(directive => directive.type === "disable" || directive.type === "enable")
420
427
  .map(directive => Object.assign({}, directive, { unprocessedDirective: directive }))
@@ -443,17 +450,38 @@ module.exports = ({ directives, disableFixes, problems, reportUnusedDisableDirec
443
450
  }
444
451
  }).sort(compareLocations);
445
452
 
453
+ // This determines a list of rules that are not being run by the given ruleFilter, if present.
454
+ const rulesToIgnore = configuredRules && ruleFilter
455
+ ? new Set(Object.keys(configuredRules).filter(ruleId => {
456
+ const severity = ConfigOps.getRuleSeverity(configuredRules[ruleId]);
457
+
458
+ // Ignore for disabled rules.
459
+ if (severity === 0) {
460
+ return false;
461
+ }
462
+
463
+ return !ruleFilter({ severity, ruleId });
464
+ }))
465
+ : new Set();
466
+
467
+ // If no ruleId is supplied that means this directive is applied to all rules, so we can't determine if it's unused if any rules are filtered out.
468
+ if (rulesToIgnore.size > 0) {
469
+ rulesToIgnore.add(null);
470
+ }
471
+
446
472
  const blockDirectivesResult = applyDirectives({
447
473
  problems,
448
474
  directives: blockDirectives,
449
475
  disableFixes,
450
- reportUnusedDisableDirectives
476
+ reportUnusedDisableDirectives,
477
+ rulesToIgnore
451
478
  });
452
479
  const lineDirectivesResult = applyDirectives({
453
480
  problems: blockDirectivesResult.problems,
454
481
  directives: lineDirectives,
455
482
  disableFixes,
456
- reportUnusedDisableDirectives
483
+ reportUnusedDisableDirectives,
484
+ rulesToIgnore
457
485
  });
458
486
 
459
487
  return reportUnusedDisableDirectives !== "off"
@@ -40,7 +40,7 @@ module.exports = class ConfigCommentParser {
40
40
 
41
41
  /**
42
42
  * Parses a list of "name:string_value" or/and "name" options divided by comma or
43
- * whitespace. Used for "global" and "exported" comments.
43
+ * whitespace. Used for "global" comments.
44
44
  * @param {string} string The string to parse.
45
45
  * @param {Comment} comment The comment node which has the string.
46
46
  * @returns {Object} Result map object of names and string values, or null values if no value was provided
@@ -105,6 +105,7 @@ const parserSymbol = Symbol.for("eslint.RuleTester.parser");
105
105
  * @property {string} [filename] the filename of the source code.
106
106
  * @property {boolean | "off" | "warn" | "error"} [reportUnusedDisableDirectives] Adds reported errors for
107
107
  * unused `eslint-disable` directives.
108
+ * @property {Function} [ruleFilter] A predicate function that determines whether a given rule should run.
108
109
  */
109
110
 
110
111
  /**
@@ -392,7 +393,7 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig) {
392
393
  }
393
394
 
394
395
  case "exported":
395
- Object.assign(exportedVariables, commentParser.parseStringConfig(directiveValue, comment));
396
+ Object.assign(exportedVariables, commentParser.parseListConfig(directiveValue, comment));
396
397
  break;
397
398
 
398
399
  case "globals":
@@ -439,6 +440,15 @@ function getDirectiveComments(sourceCode, ruleMapper, warnInlineConfig) {
439
440
  try {
440
441
  validator.validateRuleOptions(rule, name, ruleValue);
441
442
  } catch (err) {
443
+
444
+ /*
445
+ * If the rule has invalid `meta.schema`, throw the error because
446
+ * this is not an invalid inline configuration but an invalid rule.
447
+ */
448
+ if (err.code === "ESLINT_INVALID_RULE_OPTIONS_SCHEMA") {
449
+ throw err;
450
+ }
451
+
442
452
  problems.push(createLintingProblem({
443
453
  ruleId: name,
444
454
  message: err.message,
@@ -661,6 +671,12 @@ function normalizeVerifyOptions(providedOptions, config) {
661
671
  }
662
672
  }
663
673
 
674
+ let ruleFilter = providedOptions.ruleFilter;
675
+
676
+ if (typeof ruleFilter !== "function") {
677
+ ruleFilter = () => true;
678
+ }
679
+
664
680
  return {
665
681
  filename: normalizeFilename(providedOptions.filename || "<input>"),
666
682
  allowInlineConfig: !ignoreInlineConfig,
@@ -668,7 +684,8 @@ function normalizeVerifyOptions(providedOptions, config) {
668
684
  ? `your config${configNameOfNoInlineConfig}`
669
685
  : null,
670
686
  reportUnusedDisableDirectives,
671
- disableFixes: Boolean(providedOptions.disableFixes)
687
+ disableFixes: Boolean(providedOptions.disableFixes),
688
+ ruleFilter
672
689
  };
673
690
  }
674
691
 
@@ -885,12 +902,18 @@ function parse(text, languageOptions, filePath) {
885
902
 
886
903
  /**
887
904
  * Runs a rule, and gets its listeners
888
- * @param {Rule} rule A normalized rule with a `create` method
905
+ * @param {Rule} rule A rule object
889
906
  * @param {Context} ruleContext The context that should be passed to the rule
907
+ * @throws {TypeError} If `rule` is not an object with a `create` method
890
908
  * @throws {any} Any error during the rule's `create`
891
909
  * @returns {Object} A map of selector listeners provided by the rule
892
910
  */
893
911
  function createRuleListeners(rule, ruleContext) {
912
+
913
+ if (!rule || typeof rule !== "object" || typeof rule.create !== "function") {
914
+ throw new TypeError(`Error while loading rule '${ruleContext.id}': Rule must be an object with a \`create\` method`);
915
+ }
916
+
894
917
  try {
895
918
  return rule.create(ruleContext);
896
919
  } catch (ex) {
@@ -899,43 +922,6 @@ function createRuleListeners(rule, ruleContext) {
899
922
  }
900
923
  }
901
924
 
902
- // methods that exist on SourceCode object
903
- const DEPRECATED_SOURCECODE_PASSTHROUGHS = {
904
- getSource: "getText",
905
- getSourceLines: "getLines",
906
- getAllComments: "getAllComments",
907
- getNodeByRangeIndex: "getNodeByRangeIndex",
908
- getComments: "getComments",
909
- getCommentsBefore: "getCommentsBefore",
910
- getCommentsAfter: "getCommentsAfter",
911
- getCommentsInside: "getCommentsInside",
912
- getJSDocComment: "getJSDocComment",
913
- getFirstToken: "getFirstToken",
914
- getFirstTokens: "getFirstTokens",
915
- getLastToken: "getLastToken",
916
- getLastTokens: "getLastTokens",
917
- getTokenAfter: "getTokenAfter",
918
- getTokenBefore: "getTokenBefore",
919
- getTokenByRangeStart: "getTokenByRangeStart",
920
- getTokens: "getTokens",
921
- getTokensAfter: "getTokensAfter",
922
- getTokensBefore: "getTokensBefore",
923
- getTokensBetween: "getTokensBetween"
924
- };
925
-
926
-
927
- const BASE_TRAVERSAL_CONTEXT = Object.freeze(
928
- Object.keys(DEPRECATED_SOURCECODE_PASSTHROUGHS).reduce(
929
- (contextInfo, methodName) =>
930
- Object.assign(contextInfo, {
931
- [methodName](...args) {
932
- return this.sourceCode[DEPRECATED_SOURCECODE_PASSTHROUGHS[methodName]](...args);
933
- }
934
- }),
935
- {}
936
- )
937
- );
938
-
939
925
  /**
940
926
  * Runs the given rules on the given SourceCode object
941
927
  * @param {SourceCode} sourceCode A SourceCode object for the given text
@@ -948,9 +934,10 @@ const BASE_TRAVERSAL_CONTEXT = Object.freeze(
948
934
  * @param {boolean} disableFixes If true, it doesn't make `fix` properties.
949
935
  * @param {string | undefined} cwd cwd of the cli
950
936
  * @param {string} physicalFilename The full path of the file on disk without any code block information
937
+ * @param {Function} ruleFilter A predicate function to filter which rules should be executed.
951
938
  * @returns {LintMessage[]} An array of reported problems
952
939
  */
953
- function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageOptions, settings, filename, disableFixes, cwd, physicalFilename) {
940
+ function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageOptions, settings, filename, disableFixes, cwd, physicalFilename, ruleFilter) {
954
941
  const emitter = createEmitter();
955
942
  const nodeQueue = [];
956
943
  let currentNode = sourceCode.ast;
@@ -972,30 +959,22 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageO
972
959
  * properties once for each rule.
973
960
  */
974
961
  const sharedTraversalContext = Object.freeze(
975
- Object.assign(
976
- Object.create(BASE_TRAVERSAL_CONTEXT),
977
- {
978
- getAncestors: () => sourceCode.getAncestors(currentNode),
979
- getDeclaredVariables: node => sourceCode.getDeclaredVariables(node),
980
- getCwd: () => cwd,
981
- cwd,
982
- getFilename: () => filename,
983
- filename,
984
- getPhysicalFilename: () => physicalFilename || filename,
985
- physicalFilename: physicalFilename || filename,
986
- getScope: () => sourceCode.getScope(currentNode),
987
- getSourceCode: () => sourceCode,
988
- sourceCode,
989
- markVariableAsUsed: name => sourceCode.markVariableAsUsed(name, currentNode),
990
- parserOptions: {
991
- ...languageOptions.parserOptions
992
- },
993
- parserPath: parserName,
994
- languageOptions,
995
- parserServices: sourceCode.parserServices,
996
- settings
997
- }
998
- )
962
+ {
963
+ getCwd: () => cwd,
964
+ cwd,
965
+ getFilename: () => filename,
966
+ filename,
967
+ getPhysicalFilename: () => physicalFilename || filename,
968
+ physicalFilename: physicalFilename || filename,
969
+ getSourceCode: () => sourceCode,
970
+ sourceCode,
971
+ parserOptions: {
972
+ ...languageOptions.parserOptions
973
+ },
974
+ parserPath: parserName,
975
+ languageOptions,
976
+ settings
977
+ }
999
978
  );
1000
979
 
1001
980
  const lintingProblems = [];
@@ -1008,6 +987,10 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageO
1008
987
  return;
1009
988
  }
1010
989
 
990
+ if (ruleFilter && !ruleFilter({ ruleId, severity })) {
991
+ return;
992
+ }
993
+
1011
994
  const rule = ruleMapper(ruleId);
1012
995
 
1013
996
  if (!rule) {
@@ -1217,9 +1200,9 @@ class Linter {
1217
1200
  * Initialize the Linter.
1218
1201
  * @param {Object} [config] the config object
1219
1202
  * @param {string} [config.cwd] path to a directory that should be considered as the current working directory, can be undefined.
1220
- * @param {"flat"|"eslintrc"} [config.configType="eslintrc"] the type of config used.
1203
+ * @param {"flat"|"eslintrc"} [config.configType="flat"] the type of config used.
1221
1204
  */
1222
- constructor({ cwd, configType } = {}) {
1205
+ constructor({ cwd, configType = "flat" } = {}) {
1223
1206
  internalSlotsMap.set(this, {
1224
1207
  cwd: normalizeCwd(cwd),
1225
1208
  lastConfigArray: null,
@@ -1362,7 +1345,8 @@ class Linter {
1362
1345
  options.filename,
1363
1346
  options.disableFixes,
1364
1347
  slots.cwd,
1365
- providedOptions.physicalFilename
1348
+ providedOptions.physicalFilename,
1349
+ null
1366
1350
  );
1367
1351
  } catch (err) {
1368
1352
  err.message += `\nOccurred while linting ${options.filename}`;
@@ -1413,29 +1397,29 @@ class Linter {
1413
1397
  ? { filename: filenameOrOptions }
1414
1398
  : filenameOrOptions || {};
1415
1399
 
1416
- if (config) {
1417
- if (configType === "flat") {
1418
-
1419
- /*
1420
- * Because of how Webpack packages up the files, we can't
1421
- * compare directly to `FlatConfigArray` using `instanceof`
1422
- * because it's not the same `FlatConfigArray` as in the tests.
1423
- * So, we work around it by assuming an array is, in fact, a
1424
- * `FlatConfigArray` if it has a `getConfig()` method.
1425
- */
1426
- let configArray = config;
1427
-
1428
- if (!Array.isArray(config) || typeof config.getConfig !== "function") {
1429
- configArray = new FlatConfigArray(config, { basePath: cwd });
1430
- configArray.normalizeSync();
1431
- }
1400
+ const configToUse = config ?? {};
1432
1401
 
1433
- return this._distinguishSuppressedMessages(this._verifyWithFlatConfigArray(textOrSourceCode, configArray, options, true));
1434
- }
1402
+ if (configType !== "eslintrc") {
1403
+
1404
+ /*
1405
+ * Because of how Webpack packages up the files, we can't
1406
+ * compare directly to `FlatConfigArray` using `instanceof`
1407
+ * because it's not the same `FlatConfigArray` as in the tests.
1408
+ * So, we work around it by assuming an array is, in fact, a
1409
+ * `FlatConfigArray` if it has a `getConfig()` method.
1410
+ */
1411
+ let configArray = configToUse;
1435
1412
 
1436
- if (typeof config.extractConfig === "function") {
1437
- return this._distinguishSuppressedMessages(this._verifyWithConfigArray(textOrSourceCode, config, options));
1413
+ if (!Array.isArray(configToUse) || typeof configToUse.getConfig !== "function") {
1414
+ configArray = new FlatConfigArray(configToUse, { basePath: cwd });
1415
+ configArray.normalizeSync();
1438
1416
  }
1417
+
1418
+ return this._distinguishSuppressedMessages(this._verifyWithFlatConfigArray(textOrSourceCode, configArray, options, true));
1419
+ }
1420
+
1421
+ if (typeof configToUse.extractConfig === "function") {
1422
+ return this._distinguishSuppressedMessages(this._verifyWithConfigArray(textOrSourceCode, configToUse, options));
1439
1423
  }
1440
1424
 
1441
1425
  /*
@@ -1448,9 +1432,9 @@ class Linter {
1448
1432
  * So we cannot apply multiple processors.
1449
1433
  */
1450
1434
  if (options.preprocess || options.postprocess) {
1451
- return this._distinguishSuppressedMessages(this._verifyWithProcessor(textOrSourceCode, config, options));
1435
+ return this._distinguishSuppressedMessages(this._verifyWithProcessor(textOrSourceCode, configToUse, options));
1452
1436
  }
1453
- return this._distinguishSuppressedMessages(this._verifyWithoutProcessors(textOrSourceCode, config, options));
1437
+ return this._distinguishSuppressedMessages(this._verifyWithoutProcessors(textOrSourceCode, configToUse, options));
1454
1438
  }
1455
1439
 
1456
1440
  /**
@@ -1693,6 +1677,14 @@ class Linter {
1693
1677
  mergedInlineConfig.rules[ruleId] = ruleValue;
1694
1678
  } catch (err) {
1695
1679
 
1680
+ /*
1681
+ * If the rule has invalid `meta.schema`, throw the error because
1682
+ * this is not an invalid inline configuration but an invalid rule.
1683
+ */
1684
+ if (err.code === "ESLINT_INVALID_RULE_OPTIONS_SCHEMA") {
1685
+ throw err;
1686
+ }
1687
+
1696
1688
  let baseMessage = err.message.slice(
1697
1689
  err.message.startsWith("Key \"rules\":")
1698
1690
  ? err.message.indexOf(":", 12) + 1
@@ -1737,7 +1729,8 @@ class Linter {
1737
1729
  options.filename,
1738
1730
  options.disableFixes,
1739
1731
  slots.cwd,
1740
- providedOptions.physicalFilename
1732
+ providedOptions.physicalFilename,
1733
+ options.ruleFilter
1741
1734
  );
1742
1735
  } catch (err) {
1743
1736
  err.message += `\nOccurred while linting ${options.filename}`;
@@ -1768,7 +1761,9 @@ class Linter {
1768
1761
  .concat(commentDirectives.problems)
1769
1762
  .concat(inlineConfigProblems)
1770
1763
  .sort((problemA, problemB) => problemA.line - problemB.line || problemA.column - problemB.column),
1771
- reportUnusedDisableDirectives: options.reportUnusedDisableDirectives
1764
+ reportUnusedDisableDirectives: options.reportUnusedDisableDirectives,
1765
+ ruleFilter: options.ruleFilter,
1766
+ configuredRules
1772
1767
  });
1773
1768
  }
1774
1769
 
@@ -1986,17 +1981,17 @@ class Linter {
1986
1981
  /**
1987
1982
  * Defines a new linting rule.
1988
1983
  * @param {string} ruleId A unique rule identifier
1989
- * @param {Function | Rule} ruleModule Function from context to object mapping AST node types to event handlers
1984
+ * @param {Rule} rule A rule object
1990
1985
  * @returns {void}
1991
1986
  */
1992
- defineRule(ruleId, ruleModule) {
1987
+ defineRule(ruleId, rule) {
1993
1988
  assertEslintrcConfig(this);
1994
- internalSlotsMap.get(this).ruleMap.define(ruleId, ruleModule);
1989
+ internalSlotsMap.get(this).ruleMap.define(ruleId, rule);
1995
1990
  }
1996
1991
 
1997
1992
  /**
1998
1993
  * Defines many new linting rules.
1999
- * @param {Record<string, Function | Rule>} rulesToDefine map from unique rule identifier to rule
1994
+ * @param {Record<string, Rule>} rulesToDefine map from unique rule identifier to rule
2000
1995
  * @returns {void}
2001
1996
  */
2002
1997
  defineRules(rulesToDefine) {
@@ -13,18 +13,10 @@
13
13
  const builtInRules = require("../rules");
14
14
 
15
15
  //------------------------------------------------------------------------------
16
- // Helpers
16
+ // Typedefs
17
17
  //------------------------------------------------------------------------------
18
18
 
19
- /**
20
- * Normalizes a rule module to the new-style API
21
- * @param {(Function|{create: Function})} rule A rule object, which can either be a function
22
- * ("old-style") or an object with a `create` method ("new-style")
23
- * @returns {{create: Function}} A new-style rule.
24
- */
25
- function normalizeRule(rule) {
26
- return typeof rule === "function" ? Object.assign({ create: rule }, rule) : rule;
27
- }
19
+ /** @typedef {import("../shared/types").Rule} Rule */
28
20
 
29
21
  //------------------------------------------------------------------------------
30
22
  // Public Interface
@@ -41,18 +33,17 @@ class Rules {
41
33
  /**
42
34
  * Registers a rule module for rule id in storage.
43
35
  * @param {string} ruleId Rule id (file name).
44
- * @param {Function} ruleModule Rule handler.
36
+ * @param {Rule} rule Rule object.
45
37
  * @returns {void}
46
38
  */
47
- define(ruleId, ruleModule) {
48
- this._rules[ruleId] = normalizeRule(ruleModule);
39
+ define(ruleId, rule) {
40
+ this._rules[ruleId] = rule;
49
41
  }
50
42
 
51
43
  /**
52
44
  * Access rule handler by id (file name).
53
45
  * @param {string} ruleId Rule id (file name).
54
- * @returns {{create: Function, schema: JsonSchema[]}}
55
- * A rule. This is normalized to always have the new-style shape with a `create` method.
46
+ * @returns {Rule} Rule object.
56
47
  */
57
48
  get(ruleId) {
58
49
  if (typeof this._rules[ruleId] === "string") {
package/lib/options.js CHANGED
@@ -57,6 +57,8 @@ const optionator = require("optionator");
57
57
  * @property {boolean} quiet Report errors only
58
58
  * @property {boolean} [version] Output the version number
59
59
  * @property {boolean} warnIgnored Show warnings when the file list includes ignored files
60
+ * @property {boolean} [passOnNoPatterns=false] When set to true, missing patterns cause
61
+ * the linting operation to short circuit and not report any failures.
60
62
  * @property {string[]} _ Positional filenames or patterns
61
63
  */
62
64
 
@@ -168,7 +170,7 @@ module.exports = function(usingFlatConfig) {
168
170
  alias: "c",
169
171
  type: "path::String",
170
172
  description: usingFlatConfig
171
- ? "Use this configuration instead of eslint.config.js"
173
+ ? "Use this configuration instead of eslint.config.js, eslint.config.mjs, or eslint.config.cjs"
172
174
  : "Use this configuration, overriding .eslintrc.* config options if present"
173
175
  },
174
176
  envFlag,
@@ -370,6 +372,12 @@ module.exports = function(usingFlatConfig) {
370
372
  description: "Exit with exit code 2 in case of fatal error"
371
373
  },
372
374
  warnIgnoredFlag,
375
+ {
376
+ option: "pass-on-no-patterns",
377
+ type: "Boolean",
378
+ default: false,
379
+ description: "Exit with exit code 0 in case no file patterns are passed"
380
+ },
373
381
  {
374
382
  option: "debug",
375
383
  type: "Boolean",