eslint 9.19.0 → 9.20.1

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.
package/README.md CHANGED
@@ -35,7 +35,6 @@ ESLint is a tool for identifying and reporting on patterns found in ECMAScript/J
35
35
  1. [Releases](#releases)
36
36
  1. [Security Policy](#security-policy)
37
37
  1. [Semantic Versioning Policy](#semantic-versioning-policy)
38
- 1. [Stylistic Rule Updates](#stylistic-rule-updates)
39
38
  1. [License](#license)
40
39
  1. [Team](#team)
41
40
  1. [Sponsors](#sponsors)
@@ -57,6 +56,17 @@ After that, you can run ESLint on any file or directory like this:
57
56
  npx eslint yourfile.js
58
57
  ```
59
58
 
59
+ ### pnpm Installation
60
+
61
+ To use ESLint with pnpm, we recommend setting up a `.npmrc` file with at least the following settings:
62
+
63
+ ```text
64
+ auto-install-peers=true
65
+ node-linker=hoisted
66
+ ```
67
+
68
+ This ensures that pnpm installs dependencies in a way that is more compatible with npm and is less likely to produce errors.
69
+
60
70
  ## Configuration
61
71
 
62
72
  You can configure rules in your `eslint.config.js` files as in this example:
@@ -191,15 +201,6 @@ ESLint follows [semantic versioning](https://semver.org). However, due to the na
191
201
 
192
202
  According to our policy, any minor update may report more linting errors than the previous release (ex: from a bug fix). As such, we recommend using the tilde (`~`) in `package.json` e.g. `"eslint": "~3.1.0"` to guarantee the results of your builds.
193
203
 
194
- ## Stylistic Rule Updates
195
-
196
- Stylistic rules are frozen according to [our policy](https://eslint.org/blog/2020/05/changes-to-rules-policies) on how we evaluate new rules and rule changes.
197
- This means:
198
-
199
- * **Bug fixes**: We will still fix bugs in stylistic rules.
200
- * **New ECMAScript features**: We will also make sure stylistic rules are compatible with new ECMAScript features.
201
- * **New options**: We will **not** add any new options to stylistic rules unless an option is the only way to fix a bug or support a newly-added ECMAScript feature.
202
-
203
204
  ## License
204
205
 
205
206
  MIT License
@@ -318,7 +319,7 @@ to get your logo on our READMEs and [website](https://eslint.org/sponsors).
318
319
  <h3>Platinum Sponsors</h3>
319
320
  <p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="128"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="128"></a></p><h3>Gold Sponsors</h3>
320
321
  <p><a href="https://qlty.sh/"><img src="https://images.opencollective.com/qltysh/33d157d/logo.png" alt="Qlty Software" height="96"></a> <a href="https://trunk.io/"><img src="https://images.opencollective.com/trunkio/fb92d60/avatar.png" alt="trunk.io" height="96"></a></p><h3>Silver Sponsors</h3>
321
- <p><a href="https://www.serptriumph.com/"><img src="https://images.opencollective.com/serp-triumph5/fea3074/logo.png" alt="SERP Triumph" height="64"></a> <a href="https://www.jetbrains.com/"><img src="https://images.opencollective.com/jetbrains/fe76f99/logo.png" alt="JetBrains" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301" alt="American Express" height="64"></a></p><h3>Bronze Sponsors</h3>
322
+ <p><a href="https://vite.dev/"><img src="https://images.opencollective.com/vite/e6d15e1/logo.png" alt="Vite" height="64"></a> <a href="https://www.jetbrains.com/"><img src="https://images.opencollective.com/jetbrains/fe76f99/logo.png" alt="JetBrains" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301" alt="American Express" height="64"></a></p><h3>Bronze Sponsors</h3>
322
323
  <p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340" alt="GitBook" height="32"></a> <a href="https://nolebase.ayaka.io"><img src="https://avatars.githubusercontent.com/u/11081491" alt="Neko" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104" alt="Nx" height="32"></a> <a href="https://opensource.mercedes-benz.com/"><img src="https://avatars.githubusercontent.com/u/34240465" alt="Mercedes-Benz Group" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774" alt="HeroCoders" height="32"></a></p>
323
324
  <h3>Technology Sponsors</h3>
324
325
  Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.
@@ -499,11 +499,41 @@ class ConfigLoader {
499
499
  debug(`Loading config file ${configFilePath}`);
500
500
  const fileConfig = await loadConfigFile(configFilePath);
501
501
 
502
- if (Array.isArray(fileConfig)) {
503
- configs.push(...fileConfig);
504
- } else {
505
- configs.push(fileConfig);
502
+ /*
503
+ * It's possible that a config file could be empty or else
504
+ * have an empty object or array. In this case, we want to
505
+ * warn the user that they have an empty config.
506
+ *
507
+ * An empty CommonJS file exports an empty object while
508
+ * an empty ESM file exports undefined.
509
+ */
510
+
511
+ let emptyConfig = typeof fileConfig === "undefined";
512
+
513
+ debug(`Config file ${configFilePath} is ${emptyConfig ? "empty" : "not empty"}`);
514
+
515
+ if (!emptyConfig) {
516
+ if (Array.isArray(fileConfig)) {
517
+ if (fileConfig.length === 0) {
518
+ debug(`Config file ${configFilePath} is an empty array`);
519
+ emptyConfig = true;
520
+ } else {
521
+ configs.push(...fileConfig);
522
+ }
523
+ } else {
524
+ if (typeof fileConfig === "object" && fileConfig !== null && Object.keys(fileConfig).length === 0) {
525
+ debug(`Config file ${configFilePath} is an empty object`);
526
+ emptyConfig = true;
527
+ } else {
528
+ configs.push(fileConfig);
529
+ }
530
+ }
506
531
  }
532
+
533
+ if (emptyConfig) {
534
+ globalThis.process?.emitWarning?.(`Running ESLint with an empty config (from ${configFilePath}). Please double-check that this is what you want. If you want to run ESLint with an empty config, export [{}] to remove this warning.`, "ESLintEmptyConfigWarning");
535
+ }
536
+
507
537
  }
508
538
 
509
539
  // add in any configured defaults
@@ -110,7 +110,12 @@ function languageOptionsToJSON(languageOptions, objectKey = "languageOptions") {
110
110
  }
111
111
 
112
112
  if (typeof value === "function") {
113
- throw new TypeError(`Cannot serialize key "${key}" in ${objectKey}: Function values are not supported.`);
113
+ const error = new TypeError(`Cannot serialize key "${key}" in ${objectKey}: Function values are not supported.`);
114
+
115
+ error.messageTemplate = "config-serialize-function";
116
+ error.messageData = { key, objectKey };
117
+
118
+ throw error;
114
119
  }
115
120
 
116
121
  }
@@ -470,7 +470,7 @@ class ESLint {
470
470
  defaultConfigs
471
471
  };
472
472
 
473
- this.#configLoader = processedOptions.flags.includes("unstable_config_lookup_from_file")
473
+ this.#configLoader = linter.hasFlag("unstable_config_lookup_from_file")
474
474
  ? new ConfigLoader(configLoaderOptions)
475
475
  : new LegacyConfigLoader(configLoaderOptions);
476
476
 
@@ -43,7 +43,7 @@ const { assertIsRuleSeverity } = require("../config/flat-config-schema");
43
43
  const { normalizeSeverityToString, normalizeSeverityToNumber } = require("../shared/severity");
44
44
  const { deepMergeArrays } = require("../shared/deep-merge-arrays");
45
45
  const jslang = require("../languages/js");
46
- const { activeFlags, inactiveFlags } = require("../shared/flags");
46
+ const { activeFlags, inactiveFlags, getInactivityReasonMessage } = require("../shared/flags");
47
47
  const debug = require("debug")("eslint:linter");
48
48
  const MAX_AUTOFIX_PASSES = 10;
49
49
  const DEFAULT_PARSER_NAME = "espree";
@@ -1326,19 +1326,40 @@ class Linter {
1326
1326
  */
1327
1327
  constructor({ cwd, configType = "flat", flags = [] } = {}) {
1328
1328
 
1329
+ const processedFlags = [];
1330
+
1329
1331
  flags.forEach(flag => {
1330
1332
  if (inactiveFlags.has(flag)) {
1331
- throw new Error(`The flag '${flag}' is inactive: ${inactiveFlags.get(flag)}`);
1333
+ const inactiveFlagData = inactiveFlags.get(flag);
1334
+ const inactivityReason = getInactivityReasonMessage(inactiveFlagData);
1335
+
1336
+ if (typeof inactiveFlagData.replacedBy === "undefined") {
1337
+ throw new Error(`The flag '${flag}' is inactive: ${inactivityReason}`);
1338
+ }
1339
+
1340
+ // if there's a replacement, enable it instead of original
1341
+ if (typeof inactiveFlagData.replacedBy === "string") {
1342
+ processedFlags.push(inactiveFlagData.replacedBy);
1343
+ }
1344
+
1345
+ globalThis.process?.emitWarning?.(
1346
+ `The flag '${flag}' is inactive: ${inactivityReason}`,
1347
+ `ESLintInactiveFlag_${flag}`
1348
+ );
1349
+
1350
+ return;
1332
1351
  }
1333
1352
 
1334
1353
  if (!activeFlags.has(flag)) {
1335
1354
  throw new Error(`Unknown flag '${flag}'.`);
1336
1355
  }
1356
+
1357
+ processedFlags.push(flag);
1337
1358
  });
1338
1359
 
1339
1360
  internalSlotsMap.set(this, {
1340
1361
  cwd: normalizeCwd(cwd),
1341
- flags,
1362
+ flags: processedFlags,
1342
1363
  lastConfigArray: null,
1343
1364
  lastSourceCode: null,
1344
1365
  lastSuppressedMessages: [],
@@ -143,7 +143,7 @@ module.exports = {
143
143
 
144
144
  if (blockBody.length === 0) {
145
145
  messageId = "unexpectedEmptyBlock";
146
- } else if (blockBody.length > 1) {
146
+ } else if (blockBody.length > 1 || blockBody[0].type !== "ReturnStatement") {
147
147
  messageId = "unexpectedOtherBlock";
148
148
  } else if (blockBody[0].argument === null) {
149
149
  messageId = "unexpectedSingleBlock";
@@ -119,8 +119,17 @@ module.exports = {
119
119
  function ensureWasAssigned(node) {
120
120
  const scope = sourceCode.getScope(node);
121
121
 
122
+ // if this is program scope we also need to check module scope
123
+ const extraScope = node.type === "Program" && node.sourceType === "module"
124
+ ? scope.childScopes[0]
125
+ : null;
126
+
122
127
  aliases.forEach(alias => {
123
128
  checkWasAssigned(alias, scope);
129
+
130
+ if (extraScope) {
131
+ checkWasAssigned(alias, extraScope);
132
+ }
124
133
  });
125
134
  }
126
135
 
@@ -4,6 +4,23 @@
4
4
 
5
5
  "use strict";
6
6
 
7
+ //------------------------------------------------------------------------------
8
+ // Typedefs
9
+ //------------------------------------------------------------------------------
10
+
11
+ /**
12
+ * @typedef {Object} InactiveFlagData
13
+ * @property {string} description Flag description
14
+ * @property {string | null} [replacedBy] Can be either:
15
+ * - An active flag (string) that enables the same feature.
16
+ * - `null` if the feature is now enabled by default.
17
+ * - Omitted if the feature has been abandoned.
18
+ */
19
+
20
+ //-----------------------------------------------------------------------------
21
+ // Exports
22
+ //-----------------------------------------------------------------------------
23
+
7
24
  /**
8
25
  * The set of flags that change ESLint behavior with a description.
9
26
  * @type {Map<string, string>}
@@ -14,15 +31,36 @@ const activeFlags = new Map([
14
31
  ]);
15
32
 
16
33
  /**
17
- * The set of flags that used to be active but no longer have an effect.
18
- * @type {Map<string, string>}
34
+ * The set of flags that used to be active.
35
+ * @type {Map<string, InactiveFlagData>}
19
36
  */
20
37
  const inactiveFlags = new Map([
21
- ["test_only_old", "Used only for testing."],
22
- ["unstable_ts_config", "This flag is no longer required to enable TypeScript configuration files."]
38
+ ["test_only_replaced", { description: "Used only for testing flags that have been replaced by other flags.", replacedBy: "test_only" }],
39
+ ["test_only_enabled_by_default", { description: "Used only for testing flags whose features have been enabled by default.", replacedBy: null }],
40
+ ["test_only_abandoned", { description: "Used only for testing flags whose features have been abandoned." }],
41
+ ["unstable_ts_config", { description: "Enable TypeScript configuration files.", replacedBy: null }]
23
42
  ]);
24
43
 
44
+ /**
45
+ * Creates a message that describes the reason the flag is inactive.
46
+ * @param {InactiveFlagData} inactiveFlagData Data for the inactive flag.
47
+ * @returns {string} Message describing the reason the flag is inactive.
48
+ */
49
+ function getInactivityReasonMessage({ replacedBy }) {
50
+ if (typeof replacedBy === "undefined") {
51
+ return "This feature has been abandoned.";
52
+ }
53
+
54
+ if (typeof replacedBy === "string") {
55
+ return `This flag has been renamed '${replacedBy}' to reflect its stabilization. Please use '${replacedBy}' instead.`;
56
+ }
57
+
58
+ // null
59
+ return "This feature is now enabled by default.";
60
+ }
61
+
25
62
  module.exports = {
26
63
  activeFlags,
27
- inactiveFlags
64
+ inactiveFlags,
65
+ getInactivityReasonMessage
28
66
  };
@@ -26,10 +26,42 @@
26
26
  */
27
27
 
28
28
  import * as ESTree from "estree";
29
- import { Language } from "@eslint/core";
29
+ import type {
30
+ RuleVisitor,
31
+ TextSourceCode,
32
+ Language,
33
+ SourceRange,
34
+ TraversalStep,
35
+ LanguageOptions as GenericLanguageOptions,
36
+ RuleDefinition,
37
+ RuleContext as CoreRuleContext,
38
+ RuleContextTypeOptions
39
+ } from "@eslint/core";
30
40
  import { JSONSchema4 } from "json-schema";
31
41
  import { LegacyESLint } from "./use-at-your-own-risk.js";
32
42
 
43
+ /*
44
+ * Need to extend the `RuleContext` interface to include the
45
+ * deprecated methods that have not yet been removed.
46
+ * TODO: Remove in v10.0.0.
47
+ */
48
+ declare module "@eslint/core" {
49
+ interface RuleContext {
50
+
51
+ /** @deprecated Use `sourceCode.getAncestors()` instead */
52
+ getAncestors(): ESTree.Node[];
53
+
54
+ /** @deprecated Use `sourceCode.getDeclaredVariables()` instead */
55
+ getDeclaredVariables(node: ESTree.Node): Scope.Variable[];
56
+
57
+ /** @deprecated Use `sourceCode.getScope()` instead */
58
+ getScope(): Scope.Scope;
59
+
60
+ /** @deprecated Use `sourceCode.markVariableAsUsed()` instead */
61
+ markVariableAsUsed(name: string): boolean;
62
+ }
63
+ }
64
+
33
65
  export namespace AST {
34
66
  type TokenType =
35
67
  | "Boolean"
@@ -149,7 +181,12 @@ export namespace Scope {
149
181
 
150
182
  // #region SourceCode
151
183
 
152
- export class SourceCode {
184
+ export class SourceCode implements TextSourceCode<{
185
+ LangOptions: Linter.LanguageOptions;
186
+ RootNode: AST.Program;
187
+ SyntaxElementWithLoc: AST.Token | ESTree.Node;
188
+ ConfigNode: ESTree.Comment;
189
+ }> {
153
190
  text: string;
154
191
  ast: AST.Program;
155
192
  lines: string[];
@@ -163,6 +200,9 @@ export class SourceCode {
163
200
 
164
201
  static splitLines(text: string): string[];
165
202
 
203
+ getLoc(syntaxElement: AST.Token | ESTree.Node): ESTree.SourceLocation;
204
+ getRange(syntaxElement: AST.Token | ESTree.Node): SourceRange;
205
+
166
206
  getText(node?: ESTree.Node, beforeCount?: number, afterCount?: number): string;
167
207
 
168
208
  getLines(): string[];
@@ -238,6 +278,8 @@ export class SourceCode {
238
278
  ): boolean;
239
279
 
240
280
  markVariableAsUsed(name: string, refNode?: ESTree.Node): boolean;
281
+
282
+ traverse(): Iterable<TraversalStep>;
241
283
  }
242
284
 
243
285
  export namespace SourceCode {
@@ -507,21 +549,25 @@ export namespace SourceCode {
507
549
  // #endregion
508
550
 
509
551
  export namespace Rule {
510
- interface RuleModule {
511
- create(context: RuleContext): RuleListener;
512
- meta?: RuleMetaData | undefined;
513
- }
552
+
553
+ type RuleModule = RuleDefinition<{
554
+ LangOptions: Linter.LanguageOptions,
555
+ Code: SourceCode,
556
+ RuleOptions: any[],
557
+ Visitor: NodeListener,
558
+ Node: ESTree.Node,
559
+ MessageIds: string,
560
+ ExtRuleDocs: {}
561
+ }>;
514
562
 
515
563
  type NodeTypes = ESTree.Node["type"];
516
- interface NodeListener {
564
+ interface NodeListener extends RuleVisitor {
517
565
  ArrayExpression?: ((node: ESTree.ArrayExpression & NodeParentExtension) => void) | undefined;
518
566
  "ArrayExpression:exit"?: ((node: ESTree.ArrayExpression & NodeParentExtension) => void) | undefined;
519
567
  ArrayPattern?: ((node: ESTree.ArrayPattern & NodeParentExtension) => void) | undefined;
520
568
  "ArrayPattern:exit"?: ((node: ESTree.ArrayPattern & NodeParentExtension) => void) | undefined;
521
569
  ArrowFunctionExpression?: ((node: ESTree.ArrowFunctionExpression & NodeParentExtension) => void) | undefined;
522
- "ArrowFunctionExpression:exit"?:
523
- | ((node: ESTree.ArrowFunctionExpression & NodeParentExtension) => void)
524
- | undefined;
570
+ "ArrowFunctionExpression:exit"?: ((node: ESTree.ArrowFunctionExpression & NodeParentExtension) => void) | undefined;
525
571
  AssignmentExpression?: ((node: ESTree.AssignmentExpression & NodeParentExtension) => void) | undefined;
526
572
  "AssignmentExpression:exit"?: ((node: ESTree.AssignmentExpression & NodeParentExtension) => void) | undefined;
527
573
  AssignmentPattern?: ((node: ESTree.AssignmentPattern & NodeParentExtension) => void) | undefined;
@@ -559,13 +605,9 @@ export namespace Rule {
559
605
  ExportAllDeclaration?: ((node: ESTree.ExportAllDeclaration & NodeParentExtension) => void) | undefined;
560
606
  "ExportAllDeclaration:exit"?: ((node: ESTree.ExportAllDeclaration & NodeParentExtension) => void) | undefined;
561
607
  ExportDefaultDeclaration?: ((node: ESTree.ExportDefaultDeclaration & NodeParentExtension) => void) | undefined;
562
- "ExportDefaultDeclaration:exit"?:
563
- | ((node: ESTree.ExportDefaultDeclaration & NodeParentExtension) => void)
564
- | undefined;
608
+ "ExportDefaultDeclaration:exit"?: ((node: ESTree.ExportDefaultDeclaration & NodeParentExtension) => void) | undefined;
565
609
  ExportNamedDeclaration?: ((node: ESTree.ExportNamedDeclaration & NodeParentExtension) => void) | undefined;
566
- "ExportNamedDeclaration:exit"?:
567
- | ((node: ESTree.ExportNamedDeclaration & NodeParentExtension) => void)
568
- | undefined;
610
+ "ExportNamedDeclaration:exit"?: ((node: ESTree.ExportNamedDeclaration & NodeParentExtension) => void) | undefined;
569
611
  ExportSpecifier?: ((node: ESTree.ExportSpecifier & NodeParentExtension) => void) | undefined;
570
612
  "ExportSpecifier:exit"?: ((node: ESTree.ExportSpecifier & NodeParentExtension) => void) | undefined;
571
613
  ExpressionStatement?: ((node: ESTree.ExpressionStatement & NodeParentExtension) => void) | undefined;
@@ -587,15 +629,11 @@ export namespace Rule {
587
629
  ImportDeclaration?: ((node: ESTree.ImportDeclaration & NodeParentExtension) => void) | undefined;
588
630
  "ImportDeclaration:exit"?: ((node: ESTree.ImportDeclaration & NodeParentExtension) => void) | undefined;
589
631
  ImportDefaultSpecifier?: ((node: ESTree.ImportDefaultSpecifier & NodeParentExtension) => void) | undefined;
590
- "ImportDefaultSpecifier:exit"?:
591
- | ((node: ESTree.ImportDefaultSpecifier & NodeParentExtension) => void)
592
- | undefined;
632
+ "ImportDefaultSpecifier:exit"?: ((node: ESTree.ImportDefaultSpecifier & NodeParentExtension) => void) | undefined;
593
633
  ImportExpression?: ((node: ESTree.ImportExpression & NodeParentExtension) => void) | undefined;
594
634
  "ImportExpression:exit"?: ((node: ESTree.ImportExpression & NodeParentExtension) => void) | undefined;
595
635
  ImportNamespaceSpecifier?: ((node: ESTree.ImportNamespaceSpecifier & NodeParentExtension) => void) | undefined;
596
- "ImportNamespaceSpecifier:exit"?:
597
- | ((node: ESTree.ImportNamespaceSpecifier & NodeParentExtension) => void)
598
- | undefined;
636
+ "ImportNamespaceSpecifier:exit"?: ((node: ESTree.ImportNamespaceSpecifier & NodeParentExtension) => void) | undefined;
599
637
  ImportSpecifier?: ((node: ESTree.ImportSpecifier & NodeParentExtension) => void) | undefined;
600
638
  "ImportSpecifier:exit"?: ((node: ESTree.ImportSpecifier & NodeParentExtension) => void) | undefined;
601
639
  LabeledStatement?: ((node: ESTree.LabeledStatement & NodeParentExtension) => void) | undefined;
@@ -641,9 +679,7 @@ export namespace Rule {
641
679
  SwitchStatement?: ((node: ESTree.SwitchStatement & NodeParentExtension) => void) | undefined;
642
680
  "SwitchStatement:exit"?: ((node: ESTree.SwitchStatement & NodeParentExtension) => void) | undefined;
643
681
  TaggedTemplateExpression?: ((node: ESTree.TaggedTemplateExpression & NodeParentExtension) => void) | undefined;
644
- "TaggedTemplateExpression:exit"?:
645
- | ((node: ESTree.TaggedTemplateExpression & NodeParentExtension) => void)
646
- | undefined;
682
+ "TaggedTemplateExpression:exit"?: ((node: ESTree.TaggedTemplateExpression & NodeParentExtension) => void) | undefined;
647
683
  TemplateElement?: ((node: ESTree.TemplateElement & NodeParentExtension) => void) | undefined;
648
684
  "TemplateElement:exit"?: ((node: ESTree.TemplateElement & NodeParentExtension) => void) | undefined;
649
685
  TemplateLiteral?: ((node: ESTree.TemplateLiteral & NodeParentExtension) => void) | undefined;
@@ -765,39 +801,11 @@ export namespace Rule {
765
801
  hasSuggestions?: boolean | undefined;
766
802
  }
767
803
 
768
- interface RuleContext {
769
- id: string;
770
- options: any[];
771
- settings: { [name: string]: any };
772
- parserPath: string | undefined;
773
- languageOptions: Linter.LanguageOptions;
774
- parserOptions: Linter.ParserOptions;
775
- cwd: string;
776
- filename: string;
777
- physicalFilename: string;
778
- sourceCode: SourceCode;
779
-
780
- getAncestors(): ESTree.Node[];
781
-
782
- getDeclaredVariables(node: ESTree.Node): Scope.Variable[];
783
-
784
- /** @deprecated Use property `filename` directly instead */
785
- getFilename(): string;
786
-
787
- /** @deprecated Use property `physicalFilename` directly instead */
788
- getPhysicalFilename(): string;
789
-
790
- /** @deprecated Use property `cwd` directly instead */
791
- getCwd(): string;
792
-
793
- getScope(): Scope.Scope;
794
-
795
- /** @deprecated Use property `sourceCode` directly instead */
796
- getSourceCode(): SourceCode;
797
-
798
- markVariableAsUsed(name: string): boolean;
799
-
800
- report(descriptor: ReportDescriptor): void;
804
+ interface RuleContext extends CoreRuleContext<RuleContextTypeOptions & {
805
+ LangOptions: Linter.LanguageOptions;
806
+ Code: SourceCode;
807
+ Node: ESTree.Node; }> {
808
+ // report(descriptor: ReportDescriptor): void;
801
809
  }
802
810
 
803
811
  type ReportFixer = (fixer: RuleFixer) => null | Fix | IterableIterator<Fix> | Fix[];
@@ -1325,7 +1333,7 @@ export namespace Linter {
1325
1333
  [name: string]: GlobalConf;
1326
1334
  }
1327
1335
 
1328
- interface LanguageOptions {
1336
+ interface LanguageOptions extends GenericLanguageOptions {
1329
1337
  /**
1330
1338
  * The version of ECMAScript to support. May be any year (i.e., 2022) or
1331
1339
  * version (i.e., 5). Set to "latest" for the most recent supported version.
@@ -1469,7 +1477,7 @@ export namespace ESLint {
1469
1477
  environments?: Record<string, Environment> | undefined;
1470
1478
  languages?: Record<string, Language> | undefined;
1471
1479
  processors?: Record<string, Linter.Processor> | undefined;
1472
- rules?: Record<string, Rule.RuleModule> | undefined;
1480
+ rules?: Record<string, RuleDefinition> | undefined;
1473
1481
  }
1474
1482
 
1475
1483
  type FixType = "directive" | "problem" | "suggestion" | "layout";
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+
3
+ module.exports = function({ key, objectKey }) {
4
+
5
+ // special case for parsers
6
+ const isParser = objectKey === "parser" && (key === "parse" || key === "parseForESLint");
7
+ const parserMessage = `
8
+ This typically happens when you're using a custom parser that does not
9
+ provide a "meta" property, which is how ESLint determines the serialized
10
+ representation. Please open an issue with the maintainer of the custom parser
11
+ and share this link:
12
+
13
+ https://eslint.org/docs/latest/extend/custom-parsers#meta-data-in-custom-parsers
14
+ `.trim();
15
+
16
+ return `
17
+ The requested operation requires ESLint to serialize configuration data,
18
+ but the configuration key "${objectKey}.${key}" contains a function value,
19
+ which cannot be serialized.
20
+
21
+ ${
22
+ isParser ? parserMessage : "Please double-check your configuration for errors."
23
+ }
24
+
25
+ If you still have problems, please stop by https://eslint.org/chat/help to chat
26
+ with the team.
27
+ `.trimStart();
28
+ };
@@ -5,9 +5,13 @@ module.exports = function({ plugins }) {
5
5
  const isArrayOfStrings = typeof plugins[0] === "string";
6
6
 
7
7
  return `
8
- A config object has a "plugins" key defined as an array${isArrayOfStrings ? " of strings" : ""}.
8
+ A config object has a "plugins" key defined as an array${isArrayOfStrings ? " of strings" : ""}. It looks something like this:
9
9
 
10
- Flat config requires "plugins" to be an object in this form:
10
+ {
11
+ "plugins": ${JSON.stringify(plugins)}
12
+ }
13
+
14
+ Flat config requires "plugins" to be an object, like this:
11
15
 
12
16
  {
13
17
  plugins: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint",
3
- "version": "9.19.0",
3
+ "version": "9.20.1",
4
4
  "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
5
5
  "description": "An AST-based pattern checker for JavaScript.",
6
6
  "type": "commonjs",
@@ -102,9 +102,9 @@
102
102
  "@eslint-community/eslint-utils": "^4.2.0",
103
103
  "@eslint-community/regexpp": "^4.12.1",
104
104
  "@eslint/config-array": "^0.19.0",
105
- "@eslint/core": "^0.10.0",
105
+ "@eslint/core": "^0.11.0",
106
106
  "@eslint/eslintrc": "^3.2.0",
107
- "@eslint/js": "9.19.0",
107
+ "@eslint/js": "9.20.0",
108
108
  "@eslint/plugin-kit": "^0.2.5",
109
109
  "@humanfs/node": "^0.16.6",
110
110
  "@humanwhocodes/module-importer": "^1.0.1",
@@ -138,7 +138,7 @@
138
138
  "@arethetypeswrong/cli": "^0.17.0",
139
139
  "@babel/core": "^7.4.3",
140
140
  "@babel/preset-env": "^7.4.3",
141
- "@eslint/json": "^0.9.0",
141
+ "@eslint/json": "^0.10.0",
142
142
  "@trunkio/launcher": "^1.3.0",
143
143
  "@types/node": "^20.11.5",
144
144
  "@typescript-eslint/parser": "^8.4.0",