eslint 9.26.0 → 9.27.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.
@@ -14,7 +14,6 @@ const { existsSync } = require("node:fs");
14
14
  const path = require("node:path");
15
15
  const { version } = require("../../package.json");
16
16
  const { Linter } = require("../linter");
17
- const { getRuleFromConfig } = require("../config/flat-config-helpers");
18
17
  const { defaultConfig } = require("../config/default-config");
19
18
  const {
20
19
  Legacy: {
@@ -57,17 +56,21 @@ const { ConfigLoader, LegacyConfigLoader } = require("../config/config-loader");
57
56
  * @import { CLIEngineLintReport } from "./legacy-eslint.js";
58
57
  * @import { FlatConfigArray } from "../config/flat-config-array.js";
59
58
  * @import { RuleDefinition } from "@eslint/core";
60
- * @import { ConfigData, DeprecatedRuleInfo, LintMessage, LintResult, ResultsMeta } from "../shared/types.js";
61
59
  */
62
60
 
63
61
  /** @typedef {ReturnType<ConfigArray.extractConfig>} ExtractedConfig */
62
+ /** @typedef {import("../types").Linter.Config} Config */
63
+ /** @typedef {import("../types").ESLint.DeprecatedRuleUse} DeprecatedRuleInfo */
64
+ /** @typedef {import("../types").Linter.LintMessage} LintMessage */
65
+ /** @typedef {import("../types").ESLint.LintResult} LintResult */
64
66
  /** @typedef {import("../types").ESLint.Plugin} Plugin */
67
+ /** @typedef {import("../types").ESLint.ResultsMeta} ResultsMeta */
65
68
 
66
69
  /**
67
70
  * The options with which to configure the ESLint instance.
68
71
  * @typedef {Object} ESLintOptions
69
72
  * @property {boolean} [allowInlineConfig] Enable or disable inline configuration comments.
70
- * @property {ConfigData|Array<ConfigData>} [baseConfig] Base config, extended by all configs used with this instance
73
+ * @property {Config|Array<Config>} [baseConfig] Base config, extended by all configs used with this instance
71
74
  * @property {boolean} [cache] Enable result caching.
72
75
  * @property {string} [cacheLocation] The cache file to use instead of .eslintcache.
73
76
  * @property {"metadata" | "content"} [cacheStrategy] The strategy used to detect changed files.
@@ -79,7 +82,7 @@ const { ConfigLoader, LegacyConfigLoader } = require("../config/config-loader");
79
82
  * @property {boolean} [globInputPaths] Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file.
80
83
  * @property {boolean} [ignore] False disables all ignore patterns except for the default ones.
81
84
  * @property {string[]} [ignorePatterns] Ignore file patterns to use in addition to config ignores. These patterns are relative to `cwd`.
82
- * @property {ConfigData|Array<ConfigData>} [overrideConfig] Override config, overrides all configs used with this instance
85
+ * @property {Config|Array<Config>} [overrideConfig] Override config, overrides all configs used with this instance
83
86
  * @property {boolean|string} [overrideConfigFile] Searches for default config file when falsy;
84
87
  * doesn't do any config file lookup when `true`; considered to be a config filename
85
88
  * when a string.
@@ -159,7 +162,7 @@ function getOrFindUsedDeprecatedRules(eslint, maybeFilePath) {
159
162
  if (getRuleSeverity(ruleConf) === 0) {
160
163
  continue;
161
164
  }
162
- const rule = getRuleFromConfig(ruleId, config);
165
+ const rule = config.getRuleDefinition(ruleId);
163
166
  const meta = rule && rule.meta;
164
167
 
165
168
  if (meta && meta.deprecated) {
@@ -353,7 +356,7 @@ function shouldMessageBeFixed(message, config, fixTypes) {
353
356
  return fixTypes.has("directive");
354
357
  }
355
358
 
356
- const rule = message.ruleId && getRuleFromConfig(message.ruleId, config);
359
+ const rule = message.ruleId && config.getRuleDefinition(message.ruleId);
357
360
 
358
361
  return Boolean(rule && rule.meta && fixTypes.has(rule.meta.type));
359
362
  }
@@ -387,6 +390,20 @@ function getFixerForFixTypes(fix, fixTypesSet, config) {
387
390
  originalFix(message);
388
391
  }
389
392
 
393
+ /**
394
+ * Retrieves flags from the environment variable ESLINT_FLAGS.
395
+ * @param {string[]} flags The flags defined via the API.
396
+ * @returns {string[]} The merged flags to use.
397
+ */
398
+ function mergeEnvironmentFlags(flags) {
399
+ if (!process.env.ESLINT_FLAGS) {
400
+ return flags;
401
+ }
402
+
403
+ const envFlags = process.env.ESLINT_FLAGS.trim().split(/\s*,\s*/gu);
404
+ return Array.from(new Set([...envFlags, ...flags]));
405
+ }
406
+
390
407
  //-----------------------------------------------------------------------------
391
408
  // Main API
392
409
  //-----------------------------------------------------------------------------
@@ -417,7 +434,7 @@ class ESLint {
417
434
  const linter = new Linter({
418
435
  cwd: processedOptions.cwd,
419
436
  configType: "flat",
420
- flags: processedOptions.flags,
437
+ flags: mergeEnvironmentFlags(processedOptions.flags),
421
438
  });
422
439
 
423
440
  const cacheFilePath = getCacheFile(
@@ -611,7 +628,7 @@ class ESLint {
611
628
  if (!config) {
612
629
  throw createExtraneousResultsError();
613
630
  }
614
- const rule = getRuleFromConfig(ruleId, config);
631
+ const rule = config.getRuleDefinition(ruleId);
615
632
 
616
633
  // ignore unknown rules
617
634
  if (rule) {
@@ -1068,7 +1085,7 @@ class ESLint {
1068
1085
  * This is the same logic used by the ESLint CLI executable to determine
1069
1086
  * configuration for each file it processes.
1070
1087
  * @param {string} filePath The path of the file to retrieve a config object for.
1071
- * @returns {Promise<ConfigData|undefined>} A configuration object for the file
1088
+ * @returns {Promise<Config|undefined>} A configuration object for the file
1072
1089
  * or `undefined` if there is no configuration data for the object.
1073
1090
  */
1074
1091
  async calculateConfigForFile(filePath) {
@@ -30,14 +30,14 @@ const { version } = require("../../package.json");
30
30
  //------------------------------------------------------------------------------
31
31
 
32
32
  /** @typedef {import("../cli-engine/cli-engine").LintReport} CLIEngineLintReport */
33
- /** @typedef {import("../shared/types").DeprecatedRuleInfo} DeprecatedRuleInfo */
34
- /** @typedef {import("../shared/types").ConfigData} ConfigData */
35
- /** @typedef {import("../shared/types").LintMessage} LintMessage */
36
- /** @typedef {import("../shared/types").SuppressedLintMessage} SuppressedLintMessage */
37
- /** @typedef {import("../shared/types").LintResult} LintResult */
38
- /** @typedef {import("../shared/types").ResultsMeta} ResultsMeta */
33
+ /** @typedef {import("../types").ESLint.ConfigData} ConfigData */
34
+ /** @typedef {import("../types").ESLint.DeprecatedRuleUse} DeprecatedRuleInfo */
35
+ /** @typedef {import("../types").Linter.LintMessage} LintMessage */
36
+ /** @typedef {import("../types").ESLint.LintResult} LintResult */
39
37
  /** @typedef {import("../types").ESLint.Plugin} Plugin */
38
+ /** @typedef {import("../types").ESLint.ResultsMeta} ResultsMeta */
40
39
  /** @typedef {import("../types").Rule.RuleModule} Rule */
40
+ /** @typedef {import("../types").Linter.SuppressedLintMessage} SuppressedLintMessage */
41
41
 
42
42
  /**
43
43
  * The main formatter object.
@@ -53,7 +53,7 @@ const CODE_PATH_EVENTS = [
53
53
  /**
54
54
  * Validates that the given AST has the required information.
55
55
  * @param {ASTNode} ast The Program node of the AST to check.
56
- * @throws {Error} If the AST doesn't contain the correct information.
56
+ * @throws {TypeError} If the AST doesn't contain the correct information.
57
57
  * @returns {void}
58
58
  * @private
59
59
  */
@@ -147,8 +147,8 @@ function sortedMerge(tokens, comments) {
147
147
  * Normalizes a value for a global in a config
148
148
  * @param {(boolean|string|null)} configuredValue The value given for a global in configuration or in
149
149
  * a global directive comment
150
- * @returns {("readable"|"writeable"|"off")} The value normalized as a string
151
- * @throws Error if global value is invalid
150
+ * @returns {("readonly"|"writable"|"off")} The value normalized as a string
151
+ * @throws {Error} if global value is invalid
152
152
  */
153
153
  function normalizeConfigGlobal(configuredValue) {
154
154
  switch (configuredValue) {
@@ -471,6 +471,10 @@ class SourceCode extends TokenStore {
471
471
  * @type {string[]}
472
472
  */
473
473
  this.lines = [];
474
+
475
+ /**
476
+ * @type {number[]}
477
+ */
474
478
  this.lineStartIndices = [0];
475
479
 
476
480
  const lineEndingPattern = astUtils.createGlobalLinebreakMatcher();
@@ -528,7 +532,7 @@ class SourceCode extends TokenStore {
528
532
 
529
533
  /**
530
534
  * Gets the entire source text split into an array of lines.
531
- * @returns {Array} The source text as an array of lines.
535
+ * @returns {string[]} The source text as an array of lines.
532
536
  * @public
533
537
  */
534
538
  getLines() {
@@ -687,8 +691,8 @@ class SourceCode extends TokenStore {
687
691
  /**
688
692
  * Converts a source text index into a (line, column) pair.
689
693
  * @param {number} index The index of a character in a file
690
- * @throws {TypeError} If non-numeric index or index out of range.
691
- * @returns {Object} A {line, column} location object with a 0-indexed column
694
+ * @throws {TypeError|RangeError} If non-numeric index or index out of range.
695
+ * @returns {{line: number, column: number}} A {line, column} location object with a 0-indexed column
692
696
  * @public
693
697
  */
694
698
  getLocFromIndex(index) {
@@ -9,7 +9,7 @@
9
9
  // Typedefs
10
10
  //------------------------------------------------------------------------------
11
11
 
12
- /** @typedef {import("../shared/types").LintMessage} LintMessage */
12
+ /** @typedef {import("../types").Linter.LintMessage} LintMessage */
13
13
  /** @typedef {import("@eslint/core").Language} Language */
14
14
  /** @typedef {import("@eslint/core").Position} Position */
15
15
  /** @typedef {import("@eslint/core").RulesConfig} RulesConfig */
@@ -128,6 +128,17 @@ class FileContext {
128
128
  getSourceCode() {
129
129
  return this.sourceCode;
130
130
  }
131
+
132
+ /**
133
+ * Creates a new object with the current object as the prototype and
134
+ * the specified properties as its own properties.
135
+ * @param {Object} extension The properties to add to the new object.
136
+ * @returns {FileContext} A new object with the current object as the prototype
137
+ * and the specified properties as its own properties.
138
+ */
139
+ extend(extension) {
140
+ return Object.freeze(Object.assign(Object.create(this), extension));
141
+ }
131
142
  }
132
143
 
133
144
  exports.FileContext = FileContext;
@@ -34,10 +34,8 @@ const path = require("node:path"),
34
34
  SourceCodeFixer = require("./source-code-fixer"),
35
35
  timing = require("./timing"),
36
36
  ruleReplacements = require("../../conf/replacements.json");
37
- const { getRuleFromConfig } = require("../config/flat-config-helpers");
38
37
  const { FlatConfigArray } = require("../config/flat-config-array");
39
38
  const { startTime, endTime } = require("../shared/stats");
40
- const { RuleValidator } = require("../config/rule-validator");
41
39
  const { assertIsRuleSeverity } = require("../config/flat-config-schema");
42
40
  const {
43
41
  normalizeSeverityToString,
@@ -66,6 +64,7 @@ const { ParserService } = require("../services/parser-service");
66
64
  const { FileContext } = require("./file-context");
67
65
  const { ProcessorService } = require("../services/processor-service");
68
66
  const { containsDifferentProperty } = require("../shared/option-utils");
67
+ const { Config } = require("../config/config");
69
68
  const STEP_KIND_VISIT = 1;
70
69
  const STEP_KIND_CALL = 2;
71
70
 
@@ -75,17 +74,19 @@ const STEP_KIND_CALL = 2;
75
74
 
76
75
  /** @import { Language, LanguageOptions, RuleConfig, RuleDefinition, RuleSeverity } from "@eslint/core" */
77
76
 
78
- /** @typedef {import("../shared/types").ConfigData} ConfigData */
79
- /** @typedef {import("../shared/types").Environment} Environment */
80
- /** @typedef {import("../shared/types").GlobalConf} GlobalConf */
81
- /** @typedef {import("../shared/types").LintMessage} LintMessage */
82
- /** @typedef {import("../shared/types").SuppressedLintMessage} SuppressedLintMessage */
83
- /** @typedef {import("../shared/types").ParserOptions} ParserOptions */
84
- /** @typedef {import("../shared/types").Processor} Processor */
85
- /** @typedef {import("../shared/types").Times} Times */
77
+ /** @typedef {import("../types").Linter.Config} Config */
78
+ /** @typedef {import("../types").ESLint.ConfigData} ConfigData */
79
+ /** @typedef {import("../types").ESLint.Environment} Environment */
80
+ /** @typedef {import("../types").Linter.GlobalConf} GlobalConf */
86
81
  /** @typedef {import("../types").Linter.LanguageOptions} JSLanguageOptions */
87
- /** @typedef {import("../types").Linter.StringSeverity} StringSeverity */
82
+ /** @typedef {import("../types").Linter.LintMessage} LintMessage */
83
+ /** @typedef {import("../types").Linter.Parser} Parser */
84
+ /** @typedef {import("../types").Linter.ParserOptions} ParserOptions */
85
+ /** @typedef {import("../types").Linter.Processor} Processor */
88
86
  /** @typedef {import("../types").Rule.RuleModule} Rule */
87
+ /** @typedef {import("../types").Linter.StringSeverity} StringSeverity */
88
+ /** @typedef {import("../types").Linter.SuppressedLintMessage} SuppressedLintMessage */
89
+ /** @typedef {import("../types").Linter.TimePass} TimePass */
89
90
 
90
91
  /* eslint-disable jsdoc/valid-types -- https://github.com/jsdoc-type-pratt-parser/jsdoc-type-pratt-parser/issues/4#issuecomment-778805577 */
91
92
  /**
@@ -110,7 +111,7 @@ const STEP_KIND_CALL = 2;
110
111
  * @property {SourceCode|null} lastSourceCode The `SourceCode` instance that the last `verify()` call used.
111
112
  * @property {SuppressedLintMessage[]} lastSuppressedMessages The `SuppressedLintMessage[]` instance that the last `verify()` call produced.
112
113
  * @property {Map<string, Parser>} parserMap The loaded parsers.
113
- * @property {Times} times The times spent on applying a rule to a file (see `stats` option).
114
+ * @property {{ passes: TimePass[]; }} times The times spent on applying a rule to a file (see `stats` option).
114
115
  * @property {Rules} ruleMap The loaded rules.
115
116
  */
116
117
 
@@ -350,7 +351,7 @@ function asArray(value) {
350
351
 
351
352
  /**
352
353
  * Pushes a problem to inlineConfigProblems if ruleOptions are redundant.
353
- * @param {ConfigData} config Provided config.
354
+ * @param {Config} config Provided config.
354
355
  * @param {Object} loc A line/column location
355
356
  * @param {Array} problems Problems that may be added to.
356
357
  * @param {string} ruleId The rule ID.
@@ -901,7 +902,7 @@ function normalizeFilename(filename) {
901
902
  * Normalizes the possible options for `linter.verify` and `linter.verifyAndFix` to a
902
903
  * consistent shape.
903
904
  * @param {VerifyOptions} providedOptions Options
904
- * @param {ConfigData} config Config.
905
+ * @param {Config|ConfigData} config Config.
905
906
  * @returns {Required<VerifyOptions> & InternalOptions} Normalized options
906
907
  */
907
908
  function normalizeVerifyOptions(providedOptions, config) {
@@ -1184,7 +1185,7 @@ function runRules(
1184
1185
  * All rule contexts will inherit from this object. This avoids the performance penalty of copying all the
1185
1186
  * properties once for each rule.
1186
1187
  */
1187
- const sharedTraversalContext = new FileContext({
1188
+ const fileContext = new FileContext({
1188
1189
  cwd,
1189
1190
  filename,
1190
1191
  physicalFilename: physicalFilename || filename,
@@ -1200,7 +1201,7 @@ function runRules(
1200
1201
  const lintingProblems = [];
1201
1202
 
1202
1203
  Object.keys(configuredRules).forEach(ruleId => {
1203
- const severity = ConfigOps.getRuleSeverity(configuredRules[ruleId]);
1204
+ const severity = Config.getRuleNumericSeverity(configuredRules[ruleId]);
1204
1205
 
1205
1206
  // not load disabled rules
1206
1207
  if (severity === 0) {
@@ -1220,63 +1221,61 @@ function runRules(
1220
1221
 
1221
1222
  const messageIds = rule.meta && rule.meta.messages;
1222
1223
  let reportTranslator = null;
1223
- const ruleContext = Object.freeze(
1224
- Object.assign(Object.create(sharedTraversalContext), {
1225
- id: ruleId,
1226
- options: getRuleOptions(
1227
- configuredRules[ruleId],
1228
- applyDefaultOptions ? rule.meta?.defaultOptions : void 0,
1229
- ),
1230
- report(...args) {
1231
- /*
1232
- * Create a report translator lazily.
1233
- * In a vast majority of cases, any given rule reports zero errors on a given
1234
- * piece of code. Creating a translator lazily avoids the performance cost of
1235
- * creating a new translator function for each rule that usually doesn't get
1236
- * called.
1237
- *
1238
- * Using lazy report translators improves end-to-end performance by about 3%
1239
- * with Node 8.4.0.
1240
- */
1241
- if (reportTranslator === null) {
1242
- reportTranslator = createReportTranslator({
1243
- ruleId,
1244
- severity,
1245
- sourceCode,
1246
- messageIds,
1247
- disableFixes,
1248
- language,
1249
- });
1250
- }
1251
- const problem = reportTranslator(...args);
1224
+ const ruleContext = fileContext.extend({
1225
+ id: ruleId,
1226
+ options: getRuleOptions(
1227
+ configuredRules[ruleId],
1228
+ applyDefaultOptions ? rule.meta?.defaultOptions : void 0,
1229
+ ),
1230
+ report(...args) {
1231
+ /*
1232
+ * Create a report translator lazily.
1233
+ * In a vast majority of cases, any given rule reports zero errors on a given
1234
+ * piece of code. Creating a translator lazily avoids the performance cost of
1235
+ * creating a new translator function for each rule that usually doesn't get
1236
+ * called.
1237
+ *
1238
+ * Using lazy report translators improves end-to-end performance by about 3%
1239
+ * with Node 8.4.0.
1240
+ */
1241
+ if (reportTranslator === null) {
1242
+ reportTranslator = createReportTranslator({
1243
+ ruleId,
1244
+ severity,
1245
+ sourceCode,
1246
+ messageIds,
1247
+ disableFixes,
1248
+ language,
1249
+ });
1250
+ }
1251
+ const problem = reportTranslator(...args);
1252
1252
 
1253
- if (problem.fix && !(rule.meta && rule.meta.fixable)) {
1254
- throw new Error(
1255
- 'Fixable rules must set the `meta.fixable` property to "code" or "whitespace".',
1256
- );
1257
- }
1253
+ if (problem.fix && !(rule.meta && rule.meta.fixable)) {
1254
+ throw new Error(
1255
+ 'Fixable rules must set the `meta.fixable` property to "code" or "whitespace".',
1256
+ );
1257
+ }
1258
+ if (
1259
+ problem.suggestions &&
1260
+ !(rule.meta && rule.meta.hasSuggestions === true)
1261
+ ) {
1258
1262
  if (
1259
- problem.suggestions &&
1260
- !(rule.meta && rule.meta.hasSuggestions === true)
1263
+ rule.meta &&
1264
+ rule.meta.docs &&
1265
+ typeof rule.meta.docs.suggestion !== "undefined"
1261
1266
  ) {
1262
- if (
1263
- rule.meta &&
1264
- rule.meta.docs &&
1265
- typeof rule.meta.docs.suggestion !== "undefined"
1266
- ) {
1267
- // Encourage migration from the former property name.
1268
- throw new Error(
1269
- "Rules with suggestions must set the `meta.hasSuggestions` property to `true`. `meta.docs.suggestion` is ignored by ESLint.",
1270
- );
1271
- }
1267
+ // Encourage migration from the former property name.
1272
1268
  throw new Error(
1273
- "Rules with suggestions must set the `meta.hasSuggestions` property to `true`.",
1269
+ "Rules with suggestions must set the `meta.hasSuggestions` property to `true`. `meta.docs.suggestion` is ignored by ESLint.",
1274
1270
  );
1275
1271
  }
1276
- lintingProblems.push(problem);
1277
- },
1278
- }),
1279
- );
1272
+ throw new Error(
1273
+ "Rules with suggestions must set the `meta.hasSuggestions` property to `true`.",
1274
+ );
1275
+ }
1276
+ lintingProblems.push(problem);
1277
+ },
1278
+ });
1280
1279
 
1281
1280
  const ruleListenersReturn =
1282
1281
  timing.enabled || stats
@@ -1885,7 +1884,7 @@ class Linter {
1885
1884
  /**
1886
1885
  * Verify with a processor.
1887
1886
  * @param {string|SourceCode} textOrSourceCode The source code.
1888
- * @param {FlatConfig} config The config array.
1887
+ * @param {Config} config The config array.
1889
1888
  * @param {VerifyOptions&ProcessorOptions} options The options.
1890
1889
  * @param {FlatConfigArray} [configForRecursive] The `ConfigArray` object to apply multiple processors recursively.
1891
1890
  * @returns {(LintMessage|SuppressedLintMessage)[]} The found problems.
@@ -1986,7 +1985,7 @@ class Linter {
1986
1985
  /**
1987
1986
  * Verify using flat config and without any processors.
1988
1987
  * @param {VFile} file The file to lint.
1989
- * @param {FlatConfig} providedConfig An ESLintConfig instance to configure everything.
1988
+ * @param {Config} providedConfig An ESLintConfig instance to configure everything.
1990
1989
  * @param {VerifyOptions} [providedOptions] The optional filename of the file being checked.
1991
1990
  * @throws {Error} If during rule execution.
1992
1991
  * @returns {(LintMessage|SuppressedLintMessage)[]} The results as an array of messages or an empty array if no messages.
@@ -2100,15 +2099,12 @@ class Linter {
2100
2099
  }),
2101
2100
  );
2102
2101
 
2103
- // next we need to verify information about the specified rules
2104
- const ruleValidator = new RuleValidator();
2105
-
2106
2102
  for (const {
2107
2103
  config: inlineConfig,
2108
2104
  loc,
2109
2105
  } of inlineConfigResult.configs) {
2110
2106
  Object.keys(inlineConfig.rules).forEach(ruleId => {
2111
- const rule = getRuleFromConfig(ruleId, config);
2107
+ const rule = config.getRuleDefinition(ruleId);
2112
2108
  const ruleValue = inlineConfig.rules[ruleId];
2113
2109
 
2114
2110
  if (!rule) {
@@ -2218,11 +2214,8 @@ class Linter {
2218
2214
  }
2219
2215
 
2220
2216
  if (shouldValidateOptions) {
2221
- ruleValidator.validate({
2222
- plugins: config.plugins,
2223
- rules: {
2224
- [ruleId]: ruleOptions,
2225
- },
2217
+ config.validateRulesConfig({
2218
+ [ruleId]: ruleOptions,
2226
2219
  });
2227
2220
  }
2228
2221
 
@@ -2270,7 +2263,7 @@ class Linter {
2270
2263
  options.allowInlineConfig && !options.warnInlineConfig
2271
2264
  ? getDirectiveCommentsForFlatConfig(
2272
2265
  sourceCode,
2273
- ruleId => getRuleFromConfig(ruleId, config),
2266
+ ruleId => config.getRuleDefinition(ruleId),
2274
2267
  config.language,
2275
2268
  )
2276
2269
  : { problems: [], disableDirectives: [] };
@@ -2289,7 +2282,7 @@ class Linter {
2289
2282
  lintingProblems = runRules(
2290
2283
  sourceCode,
2291
2284
  configuredRules,
2292
- ruleId => getRuleFromConfig(ruleId, config),
2285
+ ruleId => config.getRuleDefinition(ruleId),
2293
2286
  void 0,
2294
2287
  config.language,
2295
2288
  languageOptions,
@@ -2348,7 +2341,7 @@ class Linter {
2348
2341
  /**
2349
2342
  * Same as linter.verify, except without support for processors.
2350
2343
  * @param {string|SourceCode} textOrSourceCode The text to parse or a SourceCode object.
2351
- * @param {FlatConfig} providedConfig An ESLintConfig instance to configure everything.
2344
+ * @param {Config} providedConfig An ESLintConfig instance to configure everything.
2352
2345
  * @param {VerifyOptions} [providedOptions] The optional filename of the file being checked.
2353
2346
  * @throws {Error} If during rule execution.
2354
2347
  * @returns {(LintMessage|SuppressedLintMessage)[]} The results as an array of messages or an empty array if no messages.
@@ -2619,7 +2612,7 @@ class Linter {
2619
2612
 
2620
2613
  /**
2621
2614
  * Gets the times spent on (parsing, fixing, linting) a file.
2622
- * @returns {LintTimes} The times.
2615
+ * @returns {{ passes: TimePass[]; }} The times.
2623
2616
  */
2624
2617
  getTimes() {
2625
2618
  return internalSlotsMap.get(this).times ?? { passes: [] };
@@ -17,7 +17,8 @@ const { interpolate } = require("./interpolate");
17
17
  // Typedefs
18
18
  //------------------------------------------------------------------------------
19
19
 
20
- /** @typedef {import("../shared/types").LintMessage} LintMessage */
20
+ /** @typedef {import("../types").Linter.LintMessage} LintMessage */
21
+ /** @typedef {import("../types").Linter.LintSuggestion} SuggestionResult */
21
22
 
22
23
  /**
23
24
  * An error message description
@@ -15,7 +15,7 @@ const assert = require("node:assert"),
15
15
  path = require("node:path"),
16
16
  equal = require("fast-deep-equal"),
17
17
  Traverser = require("../shared/traverser"),
18
- { getRuleOptionsSchema } = require("../config/flat-config-helpers"),
18
+ { Config } = require("../config/config"),
19
19
  { Linter, SourceCodeFixer } = require("../linter"),
20
20
  { interpolate, getPlaceholderMatcher } = require("../linter/interpolate"),
21
21
  stringify = require("json-stable-stringify-without-jsonify");
@@ -41,7 +41,7 @@ const { SourceCode } = require("../languages/js/source-code");
41
41
 
42
42
  /** @import { LanguageOptions, RuleDefinition } from "@eslint/core" */
43
43
 
44
- /** @typedef {import("../shared/types").Parser} Parser */
44
+ /** @typedef {import("../types").Linter.Parser} Parser */
45
45
 
46
46
  /**
47
47
  * A test case that is expected to pass lint.
@@ -767,7 +767,7 @@ class RuleTester {
767
767
  let schema;
768
768
 
769
769
  try {
770
- schema = getRuleOptionsSchema(rule);
770
+ schema = Config.getRuleOptionsSchema(rule);
771
771
  } catch (err) {
772
772
  err.message += metaSchemaDescription;
773
773
  throw err;
@@ -225,6 +225,7 @@ module.exports = new LazyLoadingRuleMap(
225
225
  "no-this-before-super": () => require("./no-this-before-super"),
226
226
  "no-throw-literal": () => require("./no-throw-literal"),
227
227
  "no-trailing-spaces": () => require("./no-trailing-spaces"),
228
+ "no-unassigned-vars": () => require("./no-unassigned-vars"),
228
229
  "no-undef": () => require("./no-undef"),
229
230
  "no-undef-init": () => require("./no-undef-init"),
230
231
  "no-undefined": () => require("./no-undefined"),
@@ -20,6 +20,8 @@ const { upperCaseFirst } = require("../shared/string-utils");
20
20
  module.exports = {
21
21
  meta: {
22
22
  type: "suggestion",
23
+ dialects: ["typescript", "javascript"],
24
+ language: "javascript",
23
25
 
24
26
  docs: {
25
27
  description:
@@ -46,6 +48,11 @@ module.exports = {
46
48
  type: "integer",
47
49
  minimum: 0,
48
50
  },
51
+ countVoidThis: {
52
+ type: "boolean",
53
+ description:
54
+ "Whether to count a `this` declaration when the type is `void`.",
55
+ },
49
56
  },
50
57
  additionalProperties: false,
51
58
  },
@@ -61,12 +68,16 @@ module.exports = {
61
68
  const sourceCode = context.sourceCode;
62
69
  const option = context.options[0];
63
70
  let numParams = 3;
71
+ let countVoidThis = false;
64
72
 
65
- if (
66
- typeof option === "object" &&
67
- (Object.hasOwn(option, "maximum") || Object.hasOwn(option, "max"))
68
- ) {
69
- numParams = option.maximum || option.max;
73
+ if (typeof option === "object") {
74
+ if (
75
+ Object.hasOwn(option, "maximum") ||
76
+ Object.hasOwn(option, "max")
77
+ ) {
78
+ numParams = option.maximum || option.max;
79
+ }
80
+ countVoidThis = option.countVoidThis;
70
81
  }
71
82
  if (typeof option === "number") {
72
83
  numParams = option;
@@ -79,7 +90,19 @@ module.exports = {
79
90
  * @private
80
91
  */
81
92
  function checkFunction(node) {
82
- if (node.params.length > numParams) {
93
+ const hasVoidThisParam =
94
+ node.params.length > 0 &&
95
+ node.params[0].type === "Identifier" &&
96
+ node.params[0].name === "this" &&
97
+ node.params[0].typeAnnotation?.typeAnnotation.type ===
98
+ "TSVoidKeyword";
99
+
100
+ const effectiveParamCount =
101
+ hasVoidThisParam && !countVoidThis
102
+ ? node.params.length - 1
103
+ : node.params.length;
104
+
105
+ if (effectiveParamCount > numParams) {
83
106
  context.report({
84
107
  loc: astUtils.getFunctionHeadLoc(node, sourceCode),
85
108
  node,
@@ -88,7 +111,7 @@ module.exports = {
88
111
  name: upperCaseFirst(
89
112
  astUtils.getFunctionNameWithKind(node),
90
113
  ),
91
- count: node.params.length,
114
+ count: effectiveParamCount,
92
115
  max: numParams,
93
116
  },
94
117
  });
@@ -99,6 +122,8 @@ module.exports = {
99
122
  FunctionDeclaration: checkFunction,
100
123
  ArrowFunctionExpression: checkFunction,
101
124
  FunctionExpression: checkFunction,
125
+ TSDeclareFunction: checkFunction,
126
+ TSFunctionType: checkFunction,
102
127
  };
103
128
  },
104
129
  };