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 +12 -11
- package/lib/config/config-loader.js +34 -4
- package/lib/config/config.js +6 -1
- package/lib/eslint/eslint.js +1 -1
- package/lib/linter/linter.js +24 -3
- package/lib/rules/arrow-body-style.js +1 -1
- package/lib/rules/consistent-this.js +9 -0
- package/lib/shared/flags.js +43 -5
- package/lib/types/index.d.ts +68 -60
- package/messages/config-serialize-function.js +28 -0
- package/messages/eslintrc-plugins.js +6 -2
- package/package.json +4 -4
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://
|
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
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
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
|
package/lib/config/config.js
CHANGED
@@ -110,7 +110,12 @@ function languageOptionsToJSON(languageOptions, objectKey = "languageOptions") {
|
|
110
110
|
}
|
111
111
|
|
112
112
|
if (typeof value === "function") {
|
113
|
-
|
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
|
}
|
package/lib/eslint/eslint.js
CHANGED
@@ -470,7 +470,7 @@ class ESLint {
|
|
470
470
|
defaultConfigs
|
471
471
|
};
|
472
472
|
|
473
|
-
this.#configLoader =
|
473
|
+
this.#configLoader = linter.hasFlag("unstable_config_lookup_from_file")
|
474
474
|
? new ConfigLoader(configLoaderOptions)
|
475
475
|
: new LegacyConfigLoader(configLoaderOptions);
|
476
476
|
|
package/lib/linter/linter.js
CHANGED
@@ -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
|
-
|
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
|
|
package/lib/shared/flags.js
CHANGED
@@ -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
|
18
|
-
* @type {Map<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
|
-
["
|
22
|
-
["
|
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
|
};
|
package/lib/types/index.d.ts
CHANGED
@@ -26,10 +26,42 @@
|
|
26
26
|
*/
|
27
27
|
|
28
28
|
import * as ESTree from "estree";
|
29
|
-
import {
|
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
|
-
|
511
|
-
|
512
|
-
|
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
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
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,
|
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
|
-
|
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.
|
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.
|
105
|
+
"@eslint/core": "^0.11.0",
|
106
106
|
"@eslint/eslintrc": "^3.2.0",
|
107
|
-
"@eslint/js": "9.
|
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.
|
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",
|