eslint 9.39.0 → 10.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +3 -3
  2. package/bin/eslint.js +1 -2
  3. package/lib/api.js +4 -15
  4. package/lib/cli.js +14 -56
  5. package/lib/config/config-loader.js +6 -154
  6. package/lib/eslint/eslint-helpers.js +5 -8
  7. package/lib/eslint/eslint.js +1 -1
  8. package/lib/eslint/index.js +0 -2
  9. package/lib/languages/js/source-code/source-code.js +41 -89
  10. package/lib/languages/js/source-code/token-store/utils.js +29 -8
  11. package/lib/linter/apply-disable-directives.js +0 -1
  12. package/lib/linter/file-context.js +0 -56
  13. package/lib/linter/file-report.js +0 -4
  14. package/lib/linter/linter.js +45 -1086
  15. package/lib/linter/rule-fixer.js +30 -0
  16. package/lib/options.js +62 -182
  17. package/lib/rule-tester/rule-tester.js +255 -194
  18. package/lib/rules/dot-notation.js +2 -2
  19. package/lib/rules/func-names.js +2 -0
  20. package/lib/rules/no-eval.js +1 -1
  21. package/lib/rules/no-invalid-regexp.js +1 -0
  22. package/lib/rules/no-shadow-restricted-names.js +1 -1
  23. package/lib/rules/no-unassigned-vars.js +1 -1
  24. package/lib/rules/no-useless-assignment.js +1 -1
  25. package/lib/rules/preserve-caught-error.js +1 -1
  26. package/lib/rules/radix.js +25 -48
  27. package/lib/services/parser-service.js +0 -1
  28. package/lib/services/processor-service.js +0 -1
  29. package/lib/services/warning-service.js +0 -11
  30. package/lib/shared/flags.js +0 -19
  31. package/lib/shared/translate-cli-options.js +106 -164
  32. package/lib/types/index.d.ts +7 -60
  33. package/lib/types/rules.d.ts +11 -2
  34. package/lib/types/use-at-your-own-risk.d.ts +1 -54
  35. package/lib/unsupported-api.js +3 -6
  36. package/package.json +14 -19
  37. package/conf/default-cli-options.js +0 -32
  38. package/lib/cli-engine/cli-engine.js +0 -1109
  39. package/lib/cli-engine/file-enumerator.js +0 -541
  40. package/lib/cli-engine/index.js +0 -7
  41. package/lib/cli-engine/load-rules.js +0 -46
  42. package/lib/eslint/legacy-eslint.js +0 -786
@@ -20,8 +20,7 @@ const { isCommentToken } = require("@eslint-community/eslint-utils"),
20
20
  VisitNodeStep,
21
21
  CallMethodStep,
22
22
  Directive,
23
- } = require("@eslint/plugin-kit"),
24
- eslintScope = require("eslint-scope");
23
+ } = require("@eslint/plugin-kit");
25
24
 
26
25
  //------------------------------------------------------------------------------
27
26
  // Type Definitions
@@ -29,6 +28,7 @@ const { isCommentToken } = require("@eslint-community/eslint-utils"),
29
28
 
30
29
  /** @typedef {import("eslint-scope").Variable} Variable */
31
30
  /** @typedef {import("eslint-scope").Scope} Scope */
31
+ /** @typedef {import("eslint-scope").ScopeManager} ScopeManager */
32
32
  /** @typedef {import("@eslint/core").SourceCode} ISourceCode */
33
33
  /** @typedef {import("@eslint/core").Directive} IDirective */
34
34
  /** @typedef {import("@eslint/core").TraversalStep} ITraversalStep */
@@ -264,103 +264,37 @@ function findLineNumberBinarySearch(lineStartIndices, target) {
264
264
  * Ensures that variables representing built-in properties of the Global Object,
265
265
  * and any globals declared by special block comments, are present in the global
266
266
  * scope.
267
- * @param {Scope} globalScope The global scope.
267
+ * @param {ScopeManager} scopeManager Scope manager.
268
268
  * @param {Object|undefined} configGlobals The globals declared in configuration
269
269
  * @param {Object|undefined} inlineGlobals The globals declared in the source code
270
270
  * @returns {void}
271
271
  */
272
272
  function addDeclaredGlobals(
273
- globalScope,
274
- configGlobals = {},
275
- inlineGlobals = {},
273
+ scopeManager,
274
+ configGlobals = Object.create(null),
275
+ inlineGlobals = Object.create(null),
276
276
  ) {
277
- // Define configured global variables.
278
- for (const id of new Set([
279
- ...Object.keys(configGlobals),
280
- ...Object.keys(inlineGlobals),
281
- ])) {
282
- /*
283
- * `normalizeConfigGlobal` will throw an error if a configured global value is invalid. However, these errors would
284
- * typically be caught when validating a config anyway (validity for inline global comments is checked separately).
285
- */
286
- const configValue =
287
- configGlobals[id] === void 0
288
- ? void 0
289
- : normalizeConfigGlobal(configGlobals[id]);
290
- const commentValue = inlineGlobals[id] && inlineGlobals[id].value;
291
- const value = commentValue || configValue;
292
- const sourceComments = inlineGlobals[id] && inlineGlobals[id].comments;
293
-
294
- if (value === "off") {
295
- continue;
296
- }
297
-
298
- let variable = globalScope.set.get(id);
299
-
300
- if (!variable) {
301
- variable = new eslintScope.Variable(id, globalScope);
302
-
303
- globalScope.variables.push(variable);
304
- globalScope.set.set(id, variable);
305
- }
277
+ const finalGlobals = { __proto__: null, ...configGlobals };
306
278
 
307
- variable.eslintImplicitGlobalSetting = configValue;
308
- variable.eslintExplicitGlobal = sourceComments !== void 0;
309
- variable.eslintExplicitGlobalComments = sourceComments;
310
- variable.writeable = value === "writable";
279
+ for (const [name, data] of Object.entries(inlineGlobals)) {
280
+ finalGlobals[name] = data.value;
311
281
  }
312
282
 
313
- /*
314
- * "through" contains all references which definitions cannot be found.
315
- * Since we augment the global scope using configuration, we need to update
316
- * references and remove the ones that were added by configuration.
317
- */
318
- globalScope.through = globalScope.through.filter(reference => {
319
- const name = reference.identifier.name;
320
- const variable = globalScope.set.get(name);
321
-
322
- if (variable) {
323
- /*
324
- * Links the variable and the reference.
325
- * And this reference is removed from `Scope#through`.
326
- */
327
- reference.resolved = variable;
328
- variable.references.push(reference);
283
+ const names = Object.keys(finalGlobals).filter(
284
+ name => finalGlobals[name] !== "off",
285
+ );
329
286
 
330
- return false;
331
- }
287
+ scopeManager.addGlobals(names);
332
288
 
333
- return true;
334
- });
289
+ const globalScope = scopeManager.scopes[0];
335
290
 
336
- /*
337
- * "implicit" contains information about implicit global variables (those created
338
- * implicitly by assigning values to undeclared variables in non-strict code).
339
- * Since we augment the global scope using configuration, we need to remove
340
- * the ones that were added by configuration, as they are either built-in
341
- * or declared elsewhere, therefore not implicit.
342
- * Since the "implicit" property was not documented, first we'll check if it exists
343
- * because it's possible that not all custom scope managers create this property.
344
- * If it exists, we assume it has properties `variables` and `set`. Property
345
- * `left` is considered optional (for example, typescript-eslint's scope manage
346
- * has this property named `leftToBeResolved`).
347
- */
348
- const { implicit } = globalScope;
349
- if (typeof implicit === "object" && implicit !== null) {
350
- implicit.variables = implicit.variables.filter(variable => {
351
- const name = variable.name;
352
- if (globalScope.set.has(name)) {
353
- implicit.set.delete(name);
354
- return false;
355
- }
356
- return true;
357
- });
291
+ for (const name of names) {
292
+ const variable = globalScope.set.get(name);
358
293
 
359
- if (implicit.left) {
360
- implicit.left = implicit.left.filter(
361
- reference => !globalScope.set.has(reference.identifier.name),
362
- );
363
- }
294
+ variable.eslintImplicitGlobalSetting = configGlobals[name];
295
+ variable.eslintExplicitGlobal = !!inlineGlobals[name];
296
+ variable.eslintExplicitGlobalComments = inlineGlobals[name]?.comments;
297
+ variable.writeable = finalGlobals[name] === "writable";
364
298
  }
365
299
  }
366
300
 
@@ -1162,6 +1096,15 @@ class SourceCode extends TokenStore {
1162
1096
  : void 0,
1163
1097
  languageOptions.globals,
1164
1098
  );
1099
+
1100
+ /*
1101
+ * `normalizeConfigGlobal` will throw an error if a configured global value is invalid. However, these errors would
1102
+ * typically be caught when validating a config anyway (validity for inline global comments is checked separately).
1103
+ */
1104
+ for (const [name, value] of Object.entries(configGlobals)) {
1105
+ configGlobals[name] = normalizeConfigGlobal(value);
1106
+ }
1107
+
1165
1108
  const varsCache = this[caches].get("vars");
1166
1109
 
1167
1110
  varsCache.set("configGlobals", configGlobals);
@@ -1243,6 +1186,15 @@ class SourceCode extends TokenStore {
1243
1186
 
1244
1187
  break;
1245
1188
  }
1189
+ case "eslint-env": {
1190
+ problems.push({
1191
+ ruleId: null,
1192
+ loc: comment.loc,
1193
+ message:
1194
+ "/* eslint-env */ comments are no longer supported.",
1195
+ });
1196
+ break;
1197
+ }
1246
1198
 
1247
1199
  // no default
1248
1200
  }
@@ -1273,7 +1225,7 @@ class SourceCode extends TokenStore {
1273
1225
  const exportedVariables = varsCache.get("exportedVariables");
1274
1226
  const globalScope = this.scopeManager.scopes[0];
1275
1227
 
1276
- addDeclaredGlobals(globalScope, configGlobals, inlineGlobals);
1228
+ addDeclaredGlobals(this.scopeManager, configGlobals, inlineGlobals);
1277
1229
 
1278
1230
  if (exportedVariables) {
1279
1231
  markExportedVariables(globalScope, exportedVariables);
@@ -1303,7 +1255,7 @@ class SourceCode extends TokenStore {
1303
1255
  new VisitNodeStep({
1304
1256
  target: node,
1305
1257
  phase: 1,
1306
- args: [node, node.parent],
1258
+ args: [node],
1307
1259
  }),
1308
1260
  );
1309
1261
  },
@@ -1312,7 +1264,7 @@ class SourceCode extends TokenStore {
1312
1264
  new VisitNodeStep({
1313
1265
  target: node,
1314
1266
  phase: 2,
1315
- args: [node, node.parent],
1267
+ args: [node],
1316
1268
  }),
1317
1269
  );
1318
1270
  },
@@ -5,7 +5,7 @@
5
5
  "use strict";
6
6
 
7
7
  //------------------------------------------------------------------------------
8
- // Exports
8
+ // Helpers
9
9
  //------------------------------------------------------------------------------
10
10
 
11
11
  /**
@@ -15,7 +15,7 @@
15
15
  * @param {number} location The location to search.
16
16
  * @returns {number} The found index or `tokens.length`.
17
17
  */
18
- exports.search = function search(tokens, location) {
18
+ function search(tokens, location) {
19
19
  for (
20
20
  let minIndex = 0, maxIndex = tokens.length - 1;
21
21
  minIndex <= maxIndex;
@@ -41,7 +41,7 @@ exports.search = function search(tokens, location) {
41
41
  }
42
42
  }
43
43
  return tokens.length;
44
- };
44
+ }
45
45
 
46
46
  /**
47
47
  * Gets the index of the `startLoc` in `tokens`.
@@ -51,7 +51,10 @@ exports.search = function search(tokens, location) {
51
51
  * @param {number} startLoc The location to get an index.
52
52
  * @returns {number} The index.
53
53
  */
54
- exports.getFirstIndex = function getFirstIndex(tokens, indexMap, startLoc) {
54
+ function getFirstIndex(tokens, indexMap, startLoc) {
55
+ if (startLoc === -1) {
56
+ return 0;
57
+ }
55
58
  if (startLoc in indexMap) {
56
59
  return indexMap[startLoc];
57
60
  }
@@ -73,9 +76,13 @@ exports.getFirstIndex = function getFirstIndex(tokens, indexMap, startLoc) {
73
76
  }
74
77
  return index + 1;
75
78
  }
76
- return 0;
77
- };
78
79
 
80
+ // Program node that doesn't start/end with a token or comment
81
+ if (startLoc === 0) {
82
+ return 0;
83
+ }
84
+ return tokens.length;
85
+ }
79
86
  /**
80
87
  * Gets the index of the `endLoc` in `tokens`.
81
88
  * The information of end locations are recorded at `endLoc - 1` in `indexMap`, so this checks about `endLoc - 1` as well.
@@ -84,7 +91,10 @@ exports.getFirstIndex = function getFirstIndex(tokens, indexMap, startLoc) {
84
91
  * @param {number} endLoc The location to get an index.
85
92
  * @returns {number} The index.
86
93
  */
87
- exports.getLastIndex = function getLastIndex(tokens, indexMap, endLoc) {
94
+ function getLastIndex(tokens, indexMap, endLoc) {
95
+ if (endLoc === -1) {
96
+ return tokens.length - 1;
97
+ }
88
98
  if (endLoc in indexMap) {
89
99
  return indexMap[endLoc] - 1;
90
100
  }
@@ -106,5 +116,16 @@ exports.getLastIndex = function getLastIndex(tokens, indexMap, endLoc) {
106
116
  }
107
117
  return index;
108
118
  }
119
+
120
+ // Program node that doesn't start/end with a token or comment
121
+ if (endLoc === 0) {
122
+ return -1;
123
+ }
109
124
  return tokens.length - 1;
110
- };
125
+ }
126
+
127
+ //------------------------------------------------------------------------------
128
+ // Exports
129
+ //------------------------------------------------------------------------------
130
+
131
+ module.exports = { search, getFirstIndex, getLastIndex };
@@ -428,7 +428,6 @@ function applyDirectives(options) {
428
428
  : column,
429
429
  severity:
430
430
  options.reportUnusedDisableDirectives === "warn" ? 1 : 2,
431
- nodeType: null,
432
431
  ...(options.disableFixes ? {} : { fix }),
433
432
  };
434
433
  },
@@ -33,20 +33,6 @@ class FileContext {
33
33
  */
34
34
  sourceCode;
35
35
 
36
- /**
37
- * The parser options for the file being linted.
38
- * @type {Record<string, unknown>}
39
- * @deprecated Use `languageOptions` instead.
40
- */
41
- parserOptions;
42
-
43
- /**
44
- * The path to the parser used to parse this file.
45
- * @type {string}
46
- * @deprecated No longer supported.
47
- */
48
- parserPath;
49
-
50
36
  /**
51
37
  * The language options used when parsing this file.
52
38
  * @type {Record<string, unknown>}
@@ -66,8 +52,6 @@ class FileContext {
66
52
  * @param {string} config.filename The filename of the file being linted.
67
53
  * @param {string} config.physicalFilename The physical filename of the file being linted.
68
54
  * @param {SourceCode} config.sourceCode The source code of the file being linted.
69
- * @param {Record<string, unknown>} config.parserOptions The parser options for the file being linted.
70
- * @param {string} config.parserPath The path to the parser used to parse this file.
71
55
  * @param {Record<string, unknown>} config.languageOptions The language options used when parsing this file.
72
56
  * @param {Record<string, unknown>} config.settings The settings for the file being linted.
73
57
  */
@@ -76,8 +60,6 @@ class FileContext {
76
60
  filename,
77
61
  physicalFilename,
78
62
  sourceCode,
79
- parserOptions,
80
- parserPath,
81
63
  languageOptions,
82
64
  settings,
83
65
  }) {
@@ -85,50 +67,12 @@ class FileContext {
85
67
  this.filename = filename;
86
68
  this.physicalFilename = physicalFilename;
87
69
  this.sourceCode = sourceCode;
88
- this.parserOptions = parserOptions;
89
- this.parserPath = parserPath;
90
70
  this.languageOptions = languageOptions;
91
71
  this.settings = settings;
92
72
 
93
73
  Object.freeze(this);
94
74
  }
95
75
 
96
- /**
97
- * Gets the current working directory.
98
- * @returns {string} The current working directory.
99
- * @deprecated Use `cwd` instead.
100
- */
101
- getCwd() {
102
- return this.cwd;
103
- }
104
-
105
- /**
106
- * Gets the filename of the file being linted.
107
- * @returns {string} The filename of the file being linted.
108
- * @deprecated Use `filename` instead.
109
- */
110
- getFilename() {
111
- return this.filename;
112
- }
113
-
114
- /**
115
- * Gets the physical filename of the file being linted.
116
- * @returns {string} The physical filename of the file being linted.
117
- * @deprecated Use `physicalFilename` instead.
118
- */
119
- getPhysicalFilename() {
120
- return this.physicalFilename;
121
- }
122
-
123
- /**
124
- * Gets the source code of the file being linted.
125
- * @returns {SourceCode} The source code of the file being linted.
126
- * @deprecated Use `sourceCode` instead.
127
- */
128
- getSourceCode() {
129
- return this.sourceCode;
130
- }
131
-
132
76
  /**
133
77
  * Creates a new object with the current object as the prototype and
134
78
  * the specified properties as its own properties.
@@ -124,7 +124,6 @@ function createLintingProblem(options, severity, language) {
124
124
  language,
125
125
  ),
126
126
  severity,
127
- nodeType: null,
128
127
  };
129
128
  }
130
129
 
@@ -340,7 +339,6 @@ function mapSuggestions(descriptor, sourceCode, messages) {
340
339
  * @param {Object} options Information about the problem
341
340
  * @param {string} options.ruleId Rule ID
342
341
  * @param {(0|1|2)} options.severity Rule severity
343
- * @param {(ASTNode|null)} options.node Node
344
342
  * @param {string} options.message Error message
345
343
  * @param {string} [options.messageId] The error message ID.
346
344
  * @param {{start: SourceLocation, end: (SourceLocation|null)}} options.loc Start and end location
@@ -362,7 +360,6 @@ function createProblem(options) {
362
360
  message: options.message,
363
361
  line: options.loc.start.line + lineOffset,
364
362
  column: options.loc.start.column + columnOffset,
365
- nodeType: (options.node && options.node.type) || null,
366
363
  };
367
364
 
368
365
  /*
@@ -548,7 +545,6 @@ class FileReport {
548
545
  createProblem({
549
546
  ruleId,
550
547
  severity,
551
- node: descriptor.node,
552
548
  message: interpolate(computedMessage, descriptor.data),
553
549
  messageId: descriptor.messageId,
554
550
  loc: descriptor.loc