eslint 9.19.0 → 9.20.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.
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)
@@ -191,15 +190,6 @@ ESLint follows [semantic versioning](https://semver.org). However, due to the na
191
190
 
192
191
  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
192
 
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
193
  ## License
204
194
 
205
195
  MIT License
@@ -318,7 +308,7 @@ to get your logo on our READMEs and [website](https://eslint.org/sponsors).
318
308
  <h3>Platinum Sponsors</h3>
319
309
  <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
310
  <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>
311
+ <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.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
312
  <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
313
  <h3>Technology Sponsors</h3>
324
314
  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,41 @@
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
+ } from "@eslint/core";
30
39
  import { JSONSchema4 } from "json-schema";
31
40
  import { LegacyESLint } from "./use-at-your-own-risk.js";
32
41
 
42
+ /*
43
+ * Need to extend the `RuleContext` interface to include the
44
+ * deprecated methods that have not yet been removed.
45
+ * TODO: Remove in v10.0.0.
46
+ */
47
+ declare module "@eslint/core" {
48
+ interface RuleContext {
49
+
50
+ /** @deprecated Use `sourceCode.getAncestors()` instead */
51
+ getAncestors(): ESTree.Node[];
52
+
53
+ /** @deprecated Use `sourceCode.getDeclaredVariables()` instead */
54
+ getDeclaredVariables(node: ESTree.Node): Scope.Variable[];
55
+
56
+ /** @deprecated Use `sourceCode.getScope()` instead */
57
+ getScope(): Scope.Scope;
58
+
59
+ /** @deprecated Use `sourceCode.markVariableAsUsed()` instead */
60
+ markVariableAsUsed(name: string): boolean;
61
+ }
62
+ }
63
+
33
64
  export namespace AST {
34
65
  type TokenType =
35
66
  | "Boolean"
@@ -149,7 +180,12 @@ export namespace Scope {
149
180
 
150
181
  // #region SourceCode
151
182
 
152
- export class SourceCode {
183
+ export class SourceCode implements TextSourceCode<{
184
+ LangOptions: Linter.LanguageOptions;
185
+ RootNode: AST.Program;
186
+ SyntaxElementWithLoc: AST.Token | ESTree.Node;
187
+ ConfigNode: ESTree.Comment;
188
+ }> {
153
189
  text: string;
154
190
  ast: AST.Program;
155
191
  lines: string[];
@@ -163,6 +199,9 @@ export class SourceCode {
163
199
 
164
200
  static splitLines(text: string): string[];
165
201
 
202
+ getLoc(syntaxElement: AST.Token | ESTree.Node): ESTree.SourceLocation;
203
+ getRange(syntaxElement: AST.Token | ESTree.Node): SourceRange;
204
+
166
205
  getText(node?: ESTree.Node, beforeCount?: number, afterCount?: number): string;
167
206
 
168
207
  getLines(): string[];
@@ -238,6 +277,8 @@ export class SourceCode {
238
277
  ): boolean;
239
278
 
240
279
  markVariableAsUsed(name: string, refNode?: ESTree.Node): boolean;
280
+
281
+ traverse(): Iterable<TraversalStep>;
241
282
  }
242
283
 
243
284
  export namespace SourceCode {
@@ -507,21 +548,25 @@ export namespace SourceCode {
507
548
  // #endregion
508
549
 
509
550
  export namespace Rule {
510
- interface RuleModule {
511
- create(context: RuleContext): RuleListener;
512
- meta?: RuleMetaData | undefined;
513
- }
551
+
552
+ type RuleModule = RuleDefinition<{
553
+ LangOptions: Linter.LanguageOptions,
554
+ Code: SourceCode,
555
+ RuleOptions: any[],
556
+ Visitor: NodeListener,
557
+ Node: ESTree.Node,
558
+ MessageIds: string,
559
+ ExtRuleDocs: {}
560
+ }>;
514
561
 
515
562
  type NodeTypes = ESTree.Node["type"];
516
- interface NodeListener {
563
+ interface NodeListener extends RuleVisitor {
517
564
  ArrayExpression?: ((node: ESTree.ArrayExpression & NodeParentExtension) => void) | undefined;
518
565
  "ArrayExpression:exit"?: ((node: ESTree.ArrayExpression & NodeParentExtension) => void) | undefined;
519
566
  ArrayPattern?: ((node: ESTree.ArrayPattern & NodeParentExtension) => void) | undefined;
520
567
  "ArrayPattern:exit"?: ((node: ESTree.ArrayPattern & NodeParentExtension) => void) | undefined;
521
568
  ArrowFunctionExpression?: ((node: ESTree.ArrowFunctionExpression & NodeParentExtension) => void) | undefined;
522
- "ArrowFunctionExpression:exit"?:
523
- | ((node: ESTree.ArrowFunctionExpression & NodeParentExtension) => void)
524
- | undefined;
569
+ "ArrowFunctionExpression:exit"?: ((node: ESTree.ArrowFunctionExpression & NodeParentExtension) => void) | undefined;
525
570
  AssignmentExpression?: ((node: ESTree.AssignmentExpression & NodeParentExtension) => void) | undefined;
526
571
  "AssignmentExpression:exit"?: ((node: ESTree.AssignmentExpression & NodeParentExtension) => void) | undefined;
527
572
  AssignmentPattern?: ((node: ESTree.AssignmentPattern & NodeParentExtension) => void) | undefined;
@@ -559,13 +604,9 @@ export namespace Rule {
559
604
  ExportAllDeclaration?: ((node: ESTree.ExportAllDeclaration & NodeParentExtension) => void) | undefined;
560
605
  "ExportAllDeclaration:exit"?: ((node: ESTree.ExportAllDeclaration & NodeParentExtension) => void) | undefined;
561
606
  ExportDefaultDeclaration?: ((node: ESTree.ExportDefaultDeclaration & NodeParentExtension) => void) | undefined;
562
- "ExportDefaultDeclaration:exit"?:
563
- | ((node: ESTree.ExportDefaultDeclaration & NodeParentExtension) => void)
564
- | undefined;
607
+ "ExportDefaultDeclaration:exit"?: ((node: ESTree.ExportDefaultDeclaration & NodeParentExtension) => void) | undefined;
565
608
  ExportNamedDeclaration?: ((node: ESTree.ExportNamedDeclaration & NodeParentExtension) => void) | undefined;
566
- "ExportNamedDeclaration:exit"?:
567
- | ((node: ESTree.ExportNamedDeclaration & NodeParentExtension) => void)
568
- | undefined;
609
+ "ExportNamedDeclaration:exit"?: ((node: ESTree.ExportNamedDeclaration & NodeParentExtension) => void) | undefined;
569
610
  ExportSpecifier?: ((node: ESTree.ExportSpecifier & NodeParentExtension) => void) | undefined;
570
611
  "ExportSpecifier:exit"?: ((node: ESTree.ExportSpecifier & NodeParentExtension) => void) | undefined;
571
612
  ExpressionStatement?: ((node: ESTree.ExpressionStatement & NodeParentExtension) => void) | undefined;
@@ -587,15 +628,11 @@ export namespace Rule {
587
628
  ImportDeclaration?: ((node: ESTree.ImportDeclaration & NodeParentExtension) => void) | undefined;
588
629
  "ImportDeclaration:exit"?: ((node: ESTree.ImportDeclaration & NodeParentExtension) => void) | undefined;
589
630
  ImportDefaultSpecifier?: ((node: ESTree.ImportDefaultSpecifier & NodeParentExtension) => void) | undefined;
590
- "ImportDefaultSpecifier:exit"?:
591
- | ((node: ESTree.ImportDefaultSpecifier & NodeParentExtension) => void)
592
- | undefined;
631
+ "ImportDefaultSpecifier:exit"?: ((node: ESTree.ImportDefaultSpecifier & NodeParentExtension) => void) | undefined;
593
632
  ImportExpression?: ((node: ESTree.ImportExpression & NodeParentExtension) => void) | undefined;
594
633
  "ImportExpression:exit"?: ((node: ESTree.ImportExpression & NodeParentExtension) => void) | undefined;
595
634
  ImportNamespaceSpecifier?: ((node: ESTree.ImportNamespaceSpecifier & NodeParentExtension) => void) | undefined;
596
- "ImportNamespaceSpecifier:exit"?:
597
- | ((node: ESTree.ImportNamespaceSpecifier & NodeParentExtension) => void)
598
- | undefined;
635
+ "ImportNamespaceSpecifier:exit"?: ((node: ESTree.ImportNamespaceSpecifier & NodeParentExtension) => void) | undefined;
599
636
  ImportSpecifier?: ((node: ESTree.ImportSpecifier & NodeParentExtension) => void) | undefined;
600
637
  "ImportSpecifier:exit"?: ((node: ESTree.ImportSpecifier & NodeParentExtension) => void) | undefined;
601
638
  LabeledStatement?: ((node: ESTree.LabeledStatement & NodeParentExtension) => void) | undefined;
@@ -641,9 +678,7 @@ export namespace Rule {
641
678
  SwitchStatement?: ((node: ESTree.SwitchStatement & NodeParentExtension) => void) | undefined;
642
679
  "SwitchStatement:exit"?: ((node: ESTree.SwitchStatement & NodeParentExtension) => void) | undefined;
643
680
  TaggedTemplateExpression?: ((node: ESTree.TaggedTemplateExpression & NodeParentExtension) => void) | undefined;
644
- "TaggedTemplateExpression:exit"?:
645
- | ((node: ESTree.TaggedTemplateExpression & NodeParentExtension) => void)
646
- | undefined;
681
+ "TaggedTemplateExpression:exit"?: ((node: ESTree.TaggedTemplateExpression & NodeParentExtension) => void) | undefined;
647
682
  TemplateElement?: ((node: ESTree.TemplateElement & NodeParentExtension) => void) | undefined;
648
683
  "TemplateElement:exit"?: ((node: ESTree.TemplateElement & NodeParentExtension) => void) | undefined;
649
684
  TemplateLiteral?: ((node: ESTree.TemplateLiteral & NodeParentExtension) => void) | undefined;
@@ -765,39 +800,8 @@ export namespace Rule {
765
800
  hasSuggestions?: boolean | undefined;
766
801
  }
767
802
 
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;
803
+ interface RuleContext extends CoreRuleContext {
804
+ // report(descriptor: ReportDescriptor): void;
801
805
  }
802
806
 
803
807
  type ReportFixer = (fixer: RuleFixer) => null | Fix | IterableIterator<Fix> | Fix[];
@@ -1325,7 +1329,7 @@ export namespace Linter {
1325
1329
  [name: string]: GlobalConf;
1326
1330
  }
1327
1331
 
1328
- interface LanguageOptions {
1332
+ interface LanguageOptions extends GenericLanguageOptions {
1329
1333
  /**
1330
1334
  * The version of ECMAScript to support. May be any year (i.e., 2022) or
1331
1335
  * version (i.e., 5). Set to "latest" for the most recent supported version.
@@ -1469,7 +1473,7 @@ export namespace ESLint {
1469
1473
  environments?: Record<string, Environment> | undefined;
1470
1474
  languages?: Record<string, Language> | undefined;
1471
1475
  processors?: Record<string, Linter.Processor> | undefined;
1472
- rules?: Record<string, Rule.RuleModule> | undefined;
1476
+ rules?: Record<string, RuleDefinition> | undefined;
1473
1477
  }
1474
1478
 
1475
1479
  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.0",
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",