eslint 9.0.0-alpha.0 → 9.0.0-alpha.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 +5 -0
- package/conf/ecma-version.js +16 -0
- package/lib/cli-engine/cli-engine.js +1 -1
- package/lib/cli-engine/lint-result-cache.js +2 -2
- package/lib/cli.js +14 -16
- package/lib/linter/apply-disable-directives.js +2 -2
- package/lib/linter/code-path-analysis/code-path.js +5 -19
- package/lib/linter/code-path-analysis/fork-context.js +1 -1
- package/lib/linter/config-comment-parser.js +7 -10
- package/lib/linter/linter.js +105 -4
- package/lib/linter/report-translator.js +2 -2
- package/lib/linter/source-code-fixer.js +1 -1
- package/lib/rule-tester/rule-tester.js +1 -26
- package/lib/rules/array-bracket-newline.js +1 -1
- package/lib/rules/array-bracket-spacing.js +1 -1
- package/lib/rules/block-scoped-var.js +1 -1
- package/lib/rules/callback-return.js +2 -2
- package/lib/rules/comma-dangle.js +1 -1
- package/lib/rules/comma-style.js +2 -2
- package/lib/rules/complexity.js +1 -1
- package/lib/rules/constructor-super.js +1 -1
- package/lib/rules/default-case.js +1 -1
- package/lib/rules/eol-last.js +2 -2
- package/lib/rules/function-paren-newline.js +2 -2
- package/lib/rules/indent-legacy.js +5 -5
- package/lib/rules/indent.js +5 -5
- package/lib/rules/index.js +1 -0
- package/lib/rules/key-spacing.js +2 -2
- package/lib/rules/line-comment-position.js +1 -1
- package/lib/rules/lines-around-directive.js +2 -2
- package/lib/rules/max-depth.js +1 -1
- package/lib/rules/max-len.js +3 -3
- package/lib/rules/max-lines.js +3 -3
- package/lib/rules/max-nested-callbacks.js +1 -1
- package/lib/rules/max-params.js +1 -1
- package/lib/rules/max-statements.js +1 -1
- package/lib/rules/multiline-comment-style.js +7 -7
- package/lib/rules/new-cap.js +1 -1
- package/lib/rules/newline-after-var.js +1 -1
- package/lib/rules/newline-before-return.js +1 -1
- package/lib/rules/no-constant-binary-expression.js +5 -5
- package/lib/rules/no-constructor-return.js +1 -1
- package/lib/rules/no-dupe-class-members.js +2 -2
- package/lib/rules/no-else-return.js +1 -1
- package/lib/rules/no-empty-function.js +2 -2
- package/lib/rules/no-fallthrough.js +1 -1
- package/lib/rules/no-inner-declarations.js +22 -1
- package/lib/rules/no-invalid-this.js +1 -1
- package/lib/rules/no-lone-blocks.js +2 -2
- package/lib/rules/no-loss-of-precision.js +1 -1
- package/lib/rules/no-misleading-character-class.js +174 -65
- package/lib/rules/no-multiple-empty-lines.js +1 -1
- package/lib/rules/no-restricted-globals.js +1 -1
- package/lib/rules/no-restricted-imports.js +2 -2
- package/lib/rules/no-restricted-modules.js +2 -2
- package/lib/rules/no-return-await.js +1 -1
- package/lib/rules/no-trailing-spaces.js +2 -3
- package/lib/rules/no-unneeded-ternary.js +1 -1
- package/lib/rules/no-unsafe-optional-chaining.js +1 -1
- package/lib/rules/no-unused-vars.js +6 -8
- package/lib/rules/no-useless-assignment.js +566 -0
- package/lib/rules/no-useless-backreference.js +1 -1
- package/lib/rules/object-curly-spacing.js +3 -3
- package/lib/rules/object-property-newline.js +1 -1
- package/lib/rules/one-var.js +5 -5
- package/lib/rules/padded-blocks.js +7 -7
- package/lib/rules/prefer-arrow-callback.js +3 -3
- package/lib/rules/prefer-reflect.js +1 -1
- package/lib/rules/prefer-regex-literals.js +1 -1
- package/lib/rules/prefer-template.js +1 -1
- package/lib/rules/radix.js +2 -2
- package/lib/rules/semi-style.js +1 -1
- package/lib/rules/sort-imports.js +1 -1
- package/lib/rules/sort-keys.js +1 -1
- package/lib/rules/sort-vars.js +1 -1
- package/lib/rules/space-unary-ops.js +1 -1
- package/lib/rules/strict.js +1 -1
- package/lib/rules/utils/ast-utils.js +7 -7
- package/lib/rules/yield-star-spacing.js +1 -1
- package/lib/source-code/source-code.js +4 -4
- package/lib/source-code/token-store/index.js +2 -2
- package/package.json +4 -4
- package/conf/config-schema.js +0 -93
- package/lib/shared/config-validator.js +0 -380
- package/lib/shared/relative-module-resolver.js +0 -50
package/README.md
CHANGED
@@ -245,6 +245,11 @@ The people who review and fix bugs and help triage issues.
|
|
245
245
|
Bryan Mishkin
|
246
246
|
</a>
|
247
247
|
</td><td align="center" valign="top" width="11%">
|
248
|
+
<a href="https://github.com/JoshuaKGoldberg">
|
249
|
+
<img src="https://github.com/JoshuaKGoldberg.png?s=75" width="75" height="75" alt="Josh Goldberg ✨'s Avatar"><br />
|
250
|
+
Josh Goldberg ✨
|
251
|
+
</a>
|
252
|
+
</td><td align="center" valign="top" width="11%">
|
248
253
|
<a href="https://github.com/fasttime">
|
249
254
|
<img src="https://github.com/fasttime.png?s=75" width="75" height="75" alt="Francesco Trotta's Avatar"><br />
|
250
255
|
Francesco Trotta
|
@@ -0,0 +1,16 @@
|
|
1
|
+
/**
|
2
|
+
* @fileoverview Configuration related to ECMAScript versions
|
3
|
+
* @author Milos Djermanovic
|
4
|
+
*/
|
5
|
+
|
6
|
+
"use strict";
|
7
|
+
|
8
|
+
/**
|
9
|
+
* The latest ECMAScript version supported by ESLint.
|
10
|
+
* @type {number} year-based ECMAScript version
|
11
|
+
*/
|
12
|
+
const LATEST_ECMA_VERSION = 2024;
|
13
|
+
|
14
|
+
module.exports = {
|
15
|
+
LATEST_ECMA_VERSION
|
16
|
+
};
|
@@ -732,7 +732,7 @@ class CLIEngine {
|
|
732
732
|
* @returns {void}
|
733
733
|
*/
|
734
734
|
static outputFixes(report) {
|
735
|
-
report.results.filter(result => Object.
|
735
|
+
report.results.filter(result => Object.hasOwn(result, "output")).forEach(result => {
|
736
736
|
fs.writeFileSync(result.filePath, result.output);
|
737
737
|
});
|
738
738
|
}
|
@@ -164,7 +164,7 @@ class LintResultCache {
|
|
164
164
|
* @returns {void}
|
165
165
|
*/
|
166
166
|
setCachedLintResults(filePath, config, result) {
|
167
|
-
if (result && Object.
|
167
|
+
if (result && Object.hasOwn(result, "output")) {
|
168
168
|
return;
|
169
169
|
}
|
170
170
|
|
@@ -181,7 +181,7 @@ class LintResultCache {
|
|
181
181
|
* In `getCachedLintResults`, if source is explicitly null, we will
|
182
182
|
* read the file from the filesystem to set the value again.
|
183
183
|
*/
|
184
|
-
if (Object.
|
184
|
+
if (Object.hasOwn(resultToSerialize, "source")) {
|
185
185
|
resultToSerialize.source = null;
|
186
186
|
}
|
187
187
|
|
package/lib/cli.js
CHANGED
@@ -285,25 +285,23 @@ async function printResults(engine, results, format, outputFile, resultsMeta) {
|
|
285
285
|
|
286
286
|
const output = await formatter.format(results, resultsMeta);
|
287
287
|
|
288
|
-
if (
|
289
|
-
|
290
|
-
const filePath = path.resolve(process.cwd(), outputFile);
|
288
|
+
if (outputFile) {
|
289
|
+
const filePath = path.resolve(process.cwd(), outputFile);
|
291
290
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
291
|
+
if (await isDirectory(filePath)) {
|
292
|
+
log.error("Cannot write to output file path, it is a directory: %s", outputFile);
|
293
|
+
return false;
|
294
|
+
}
|
296
295
|
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
}
|
304
|
-
} else {
|
305
|
-
log.info(output);
|
296
|
+
try {
|
297
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
298
|
+
await writeFile(filePath, output);
|
299
|
+
} catch (ex) {
|
300
|
+
log.error("There was a problem writing the output file:\n%s", ex);
|
301
|
+
return false;
|
306
302
|
}
|
303
|
+
} else if (output) {
|
304
|
+
log.info(output);
|
307
305
|
}
|
308
306
|
|
309
307
|
return true;
|
@@ -171,7 +171,7 @@ function createCommentRemoval(directives, commentToken) {
|
|
171
171
|
return {
|
172
172
|
description: ruleIds.length <= 2
|
173
173
|
? ruleIds.join(" or ")
|
174
|
-
: `${ruleIds.slice(0, ruleIds.length - 1).join(", ")}, or ${ruleIds
|
174
|
+
: `${ruleIds.slice(0, ruleIds.length - 1).join(", ")}, or ${ruleIds.at(-1)}`,
|
175
175
|
fix: {
|
176
176
|
range,
|
177
177
|
text: " "
|
@@ -342,7 +342,7 @@ function applyDirectives(options) {
|
|
342
342
|
problem.suppressions = problem.suppressions.concat(suppressions);
|
343
343
|
} else {
|
344
344
|
problem.suppressions = suppressions;
|
345
|
-
usedDisableDirectives.add(disableDirectivesForProblem
|
345
|
+
usedDisableDirectives.add(disableDirectivesForProblem.at(-1));
|
346
346
|
}
|
347
347
|
}
|
348
348
|
|
@@ -125,20 +125,6 @@ class CodePath {
|
|
125
125
|
return this.internal.thrownForkContext;
|
126
126
|
}
|
127
127
|
|
128
|
-
/**
|
129
|
-
* Tracks the traversal of the code path through each segment. This array
|
130
|
-
* starts empty and segments are added or removed as the code path is
|
131
|
-
* traversed. This array always ends up empty at the end of a code path
|
132
|
-
* traversal. The `CodePathState` uses this to track its progress through
|
133
|
-
* the code path.
|
134
|
-
* This is a passthrough to the underlying `CodePathState`.
|
135
|
-
* @type {CodePathSegment[]}
|
136
|
-
* @deprecated
|
137
|
-
*/
|
138
|
-
get currentSegments() {
|
139
|
-
return this.internal.currentSegments;
|
140
|
-
}
|
141
|
-
|
142
128
|
/**
|
143
129
|
* Traverses all segments in this code path.
|
144
130
|
*
|
@@ -180,9 +166,9 @@ class CodePath {
|
|
180
166
|
const lastSegment = resolvedOptions.last;
|
181
167
|
|
182
168
|
// set up initial location information
|
183
|
-
let record
|
184
|
-
let index
|
185
|
-
let end
|
169
|
+
let record;
|
170
|
+
let index;
|
171
|
+
let end;
|
186
172
|
let segment = null;
|
187
173
|
|
188
174
|
// segments that have already been visited during traversal
|
@@ -210,7 +196,7 @@ class CodePath {
|
|
210
196
|
if (stack.length <= 1) {
|
211
197
|
broken = true;
|
212
198
|
} else {
|
213
|
-
skippedSegment = stack
|
199
|
+
skippedSegment = stack.at(-2)[0];
|
214
200
|
}
|
215
201
|
},
|
216
202
|
|
@@ -251,7 +237,7 @@ class CodePath {
|
|
251
237
|
* Otherwise, we just read the value and sometimes modify the
|
252
238
|
* record as we traverse.
|
253
239
|
*/
|
254
|
-
record = stack
|
240
|
+
record = stack.at(-1);
|
255
241
|
segment = record[0];
|
256
242
|
index = record[1];
|
257
243
|
|
@@ -75,11 +75,9 @@ module.exports = class ConfigCommentParser {
|
|
75
75
|
parseJsonConfig(string, location) {
|
76
76
|
debug("Parsing JSON config");
|
77
77
|
|
78
|
-
let items = {};
|
79
|
-
|
80
78
|
// Parses a JSON-like comment by the same way as parsing CLI option.
|
81
79
|
try {
|
82
|
-
items = levn.parse("Object", string) || {};
|
80
|
+
const items = levn.parse("Object", string) || {};
|
83
81
|
|
84
82
|
// Some tests say that it should ignore invalid comments such as `/*eslint no-alert:abc*/`.
|
85
83
|
// Also, commaless notations have invalid severity:
|
@@ -102,11 +100,15 @@ module.exports = class ConfigCommentParser {
|
|
102
100
|
* Optionator cannot parse commaless notations.
|
103
101
|
* But we are supporting that. So this is a fallback for that.
|
104
102
|
*/
|
105
|
-
items = {};
|
106
103
|
const normalizedString = string.replace(/([-a-zA-Z0-9/]+):/gu, "\"$1\":").replace(/(\]|[0-9])\s+(?=")/u, "$1,");
|
107
104
|
|
108
105
|
try {
|
109
|
-
items = JSON.parse(`{${normalizedString}}`);
|
106
|
+
const items = JSON.parse(`{${normalizedString}}`);
|
107
|
+
|
108
|
+
return {
|
109
|
+
success: true,
|
110
|
+
config: items
|
111
|
+
};
|
110
112
|
} catch (ex) {
|
111
113
|
debug("Manual parsing failed.");
|
112
114
|
|
@@ -124,11 +126,6 @@ module.exports = class ConfigCommentParser {
|
|
124
126
|
};
|
125
127
|
|
126
128
|
}
|
127
|
-
|
128
|
-
return {
|
129
|
-
success: true,
|
130
|
-
config: items
|
131
|
-
};
|
132
129
|
}
|
133
130
|
|
134
131
|
/**
|
package/lib/linter/linter.js
CHANGED
@@ -52,6 +52,7 @@ const DEFAULT_ECMA_VERSION = 5;
|
|
52
52
|
const commentParser = new ConfigCommentParser();
|
53
53
|
const DEFAULT_ERROR_LOC = { start: { line: 1, column: 0 }, end: { line: 1, column: 1 } };
|
54
54
|
const parserSymbol = Symbol.for("eslint.RuleTester.parser");
|
55
|
+
const { LATEST_ECMA_VERSION } = require("../../conf/ecma-version");
|
55
56
|
|
56
57
|
//------------------------------------------------------------------------------
|
57
58
|
// Typedefs
|
@@ -231,7 +232,7 @@ function addDeclaredGlobals(globalScope, configGlobals, { exportedVariables, ena
|
|
231
232
|
* @private
|
232
233
|
*/
|
233
234
|
function createMissingRuleMessage(ruleId) {
|
234
|
-
return Object.
|
235
|
+
return Object.hasOwn(ruleReplacements.rules, ruleId)
|
235
236
|
? `Rule '${ruleId}' was removed and replaced by: ${ruleReplacements.rules[ruleId].join(", ")}`
|
236
237
|
: `Definition for rule '${ruleId}' was not found.`;
|
237
238
|
}
|
@@ -594,7 +595,7 @@ function normalizeEcmaVersionForLanguageOptions(ecmaVersion) {
|
|
594
595
|
* that is used for a number of processes inside of ESLint. It's normally
|
595
596
|
* safe to assume people want the latest unless otherwise specified.
|
596
597
|
*/
|
597
|
-
return
|
598
|
+
return LATEST_ECMA_VERSION;
|
598
599
|
}
|
599
600
|
|
600
601
|
const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)(?:\*\/|$)/gsu;
|
@@ -1331,7 +1332,56 @@ class Linter {
|
|
1331
1332
|
{ exportedVariables: commentDirectives.exportedVariables, enabledGlobals: commentDirectives.enabledGlobals }
|
1332
1333
|
);
|
1333
1334
|
|
1335
|
+
/*
|
1336
|
+
* Now we determine the final configurations for rules.
|
1337
|
+
* First, let all inline rule configurations override those from the config.
|
1338
|
+
* Then, check for a special case: if a rule is configured in both places,
|
1339
|
+
* inline rule configuration that only has severity should retain options from
|
1340
|
+
* the config and just override the severity.
|
1341
|
+
*
|
1342
|
+
* Example:
|
1343
|
+
*
|
1344
|
+
* {
|
1345
|
+
* rules: {
|
1346
|
+
* curly: ["error", "multi"]
|
1347
|
+
* }
|
1348
|
+
* }
|
1349
|
+
*
|
1350
|
+
* /* eslint curly: ["warn"] * /
|
1351
|
+
*
|
1352
|
+
* Results in:
|
1353
|
+
*
|
1354
|
+
* curly: ["warn", "multi"]
|
1355
|
+
*/
|
1334
1356
|
const configuredRules = Object.assign({}, config.rules, commentDirectives.configuredRules);
|
1357
|
+
|
1358
|
+
if (config.rules) {
|
1359
|
+
for (const [ruleId, ruleInlineConfig] of Object.entries(commentDirectives.configuredRules)) {
|
1360
|
+
if (
|
1361
|
+
|
1362
|
+
/*
|
1363
|
+
* If inline config for the rule has only severity
|
1364
|
+
*/
|
1365
|
+
(!Array.isArray(ruleInlineConfig) || ruleInlineConfig.length === 1) &&
|
1366
|
+
|
1367
|
+
/*
|
1368
|
+
* And provided config for the rule has options
|
1369
|
+
*/
|
1370
|
+
Object.hasOwn(config.rules, ruleId) &&
|
1371
|
+
(Array.isArray(config.rules[ruleId]) && config.rules[ruleId].length > 1)
|
1372
|
+
) {
|
1373
|
+
|
1374
|
+
/*
|
1375
|
+
* Then use severity from the inline config and options from the provided config
|
1376
|
+
*/
|
1377
|
+
configuredRules[ruleId] = [
|
1378
|
+
Array.isArray(ruleInlineConfig) ? ruleInlineConfig[0] : ruleInlineConfig, // severity from the inline config
|
1379
|
+
...config.rules[ruleId].slice(1) // options from the provided config
|
1380
|
+
];
|
1381
|
+
}
|
1382
|
+
}
|
1383
|
+
}
|
1384
|
+
|
1335
1385
|
let lintingProblems;
|
1336
1386
|
|
1337
1387
|
try {
|
@@ -1674,7 +1724,7 @@ class Linter {
|
|
1674
1724
|
[ruleId]: ruleOptions
|
1675
1725
|
}
|
1676
1726
|
});
|
1677
|
-
mergedInlineConfig.rules[ruleId] =
|
1727
|
+
mergedInlineConfig.rules[ruleId] = ruleOptions;
|
1678
1728
|
} catch (err) {
|
1679
1729
|
|
1680
1730
|
/*
|
@@ -1713,7 +1763,58 @@ class Linter {
|
|
1713
1763
|
)
|
1714
1764
|
: { problems: [], disableDirectives: [] };
|
1715
1765
|
|
1766
|
+
/*
|
1767
|
+
* Now we determine the final configurations for rules.
|
1768
|
+
* First, let all inline rule configurations override those from the config.
|
1769
|
+
* Then, check for a special case: if a rule is configured in both places,
|
1770
|
+
* inline rule configuration that only has severity should retain options from
|
1771
|
+
* the config and just override the severity.
|
1772
|
+
*
|
1773
|
+
* Example:
|
1774
|
+
*
|
1775
|
+
* {
|
1776
|
+
* rules: {
|
1777
|
+
* curly: ["error", "multi"]
|
1778
|
+
* }
|
1779
|
+
* }
|
1780
|
+
*
|
1781
|
+
* /* eslint curly: ["warn"] * /
|
1782
|
+
*
|
1783
|
+
* Results in:
|
1784
|
+
*
|
1785
|
+
* curly: ["warn", "multi"]
|
1786
|
+
*
|
1787
|
+
* At this point, all rule configurations are normalized to arrays.
|
1788
|
+
*/
|
1716
1789
|
const configuredRules = Object.assign({}, config.rules, mergedInlineConfig.rules);
|
1790
|
+
|
1791
|
+
if (config.rules) {
|
1792
|
+
for (const [ruleId, ruleInlineConfig] of Object.entries(mergedInlineConfig.rules)) {
|
1793
|
+
if (
|
1794
|
+
|
1795
|
+
/*
|
1796
|
+
* If inline config for the rule has only severity
|
1797
|
+
*/
|
1798
|
+
ruleInlineConfig.length === 1 &&
|
1799
|
+
|
1800
|
+
/*
|
1801
|
+
* And provided config for the rule has options
|
1802
|
+
*/
|
1803
|
+
Object.hasOwn(config.rules, ruleId) &&
|
1804
|
+
config.rules[ruleId].length > 1
|
1805
|
+
) {
|
1806
|
+
|
1807
|
+
/*
|
1808
|
+
* Then use severity from the inline config and options from the provided config
|
1809
|
+
*/
|
1810
|
+
configuredRules[ruleId] = [
|
1811
|
+
ruleInlineConfig[0], // severity from the inline config
|
1812
|
+
...config.rules[ruleId].slice(1) // options from the provided config
|
1813
|
+
];
|
1814
|
+
}
|
1815
|
+
}
|
1816
|
+
}
|
1817
|
+
|
1717
1818
|
let lintingProblems;
|
1718
1819
|
|
1719
1820
|
sourceCode.finalize();
|
@@ -2039,7 +2140,7 @@ class Linter {
|
|
2039
2140
|
* SourceCodeFixer.
|
2040
2141
|
*/
|
2041
2142
|
verifyAndFix(text, config, options) {
|
2042
|
-
let messages
|
2143
|
+
let messages,
|
2043
2144
|
fixedResult,
|
2044
2145
|
fixed = false,
|
2045
2146
|
passNumber = 0,
|
@@ -160,7 +160,7 @@ function mergeFixes(fixes, sourceCode) {
|
|
160
160
|
|
161
161
|
const originalText = sourceCode.text;
|
162
162
|
const start = fixes[0].range[0];
|
163
|
-
const end = fixes
|
163
|
+
const end = fixes.at(-1).range[1];
|
164
164
|
let text = "";
|
165
165
|
let lastPos = Number.MIN_SAFE_INTEGER;
|
166
166
|
|
@@ -343,7 +343,7 @@ module.exports = function createReportTranslator(metadata) {
|
|
343
343
|
if (descriptor.message) {
|
344
344
|
throw new TypeError("context.report() called with a message and a messageId. Please only pass one.");
|
345
345
|
}
|
346
|
-
if (!messages || !Object.
|
346
|
+
if (!messages || !Object.hasOwn(messages, id)) {
|
347
347
|
throw new TypeError(`context.report() called with a messageId of '${id}' which is not present in the 'messages' config: ${JSON.stringify(messages, null, 2)}`);
|
348
348
|
}
|
349
349
|
computedMessage = messages[id];
|
@@ -107,7 +107,7 @@ SourceCodeFixer.applyFixes = function(sourceText, messages, shouldFix) {
|
|
107
107
|
}
|
108
108
|
|
109
109
|
messages.forEach(problem => {
|
110
|
-
if (Object.
|
110
|
+
if (Object.hasOwn(problem, "fix")) {
|
111
111
|
fixes.push(problem);
|
112
112
|
} else {
|
113
113
|
remainingMessages.push(problem);
|
@@ -16,8 +16,7 @@ const
|
|
16
16
|
equal = require("fast-deep-equal"),
|
17
17
|
Traverser = require("../shared/traverser"),
|
18
18
|
{ getRuleOptionsSchema } = require("../config/flat-config-helpers"),
|
19
|
-
{ Linter, SourceCodeFixer, interpolate } = require("../linter")
|
20
|
-
CodePath = require("../linter/code-path-analysis/code-path");
|
19
|
+
{ Linter, SourceCodeFixer, interpolate } = require("../linter");
|
21
20
|
|
22
21
|
const { FlatConfigArray } = require("../config/flat-config-array");
|
23
22
|
const { defaultConfig } = require("../config/default-config");
|
@@ -274,21 +273,6 @@ function wrapParser(parser) {
|
|
274
273
|
};
|
275
274
|
}
|
276
275
|
|
277
|
-
/**
|
278
|
-
* Emit a deprecation warning if rule uses CodePath#currentSegments.
|
279
|
-
* @param {string} ruleName Name of the rule.
|
280
|
-
* @returns {void}
|
281
|
-
*/
|
282
|
-
function emitCodePathCurrentSegmentsWarning(ruleName) {
|
283
|
-
if (!emitCodePathCurrentSegmentsWarning[`warned-${ruleName}`]) {
|
284
|
-
emitCodePathCurrentSegmentsWarning[`warned-${ruleName}`] = true;
|
285
|
-
process.emitWarning(
|
286
|
-
`"${ruleName}" rule uses CodePath#currentSegments and will stop working in ESLint v9. Please read the documentation for how to update your code: https://eslint.org/docs/latest/extend/code-path-analysis#usage-examples`,
|
287
|
-
"DeprecationWarning"
|
288
|
-
);
|
289
|
-
}
|
290
|
-
}
|
291
|
-
|
292
276
|
/**
|
293
277
|
* Function to replace forbidden `SourceCode` methods. Allows just one call per method.
|
294
278
|
* @param {string} methodName The name of the method to forbid.
|
@@ -753,24 +737,15 @@ class RuleTester {
|
|
753
737
|
|
754
738
|
// Verify the code.
|
755
739
|
const { applyLanguageOptions, applyInlineConfig, finalize } = SourceCode.prototype;
|
756
|
-
const originalCurrentSegments = Object.getOwnPropertyDescriptor(CodePath.prototype, "currentSegments");
|
757
740
|
let messages;
|
758
741
|
|
759
742
|
try {
|
760
|
-
Object.defineProperty(CodePath.prototype, "currentSegments", {
|
761
|
-
get() {
|
762
|
-
emitCodePathCurrentSegmentsWarning(ruleName);
|
763
|
-
return originalCurrentSegments.get.call(this);
|
764
|
-
}
|
765
|
-
});
|
766
|
-
|
767
743
|
forbiddenMethods.forEach(methodName => {
|
768
744
|
SourceCode.prototype[methodName] = throwForbiddenMethodError(methodName, SourceCode.prototype);
|
769
745
|
});
|
770
746
|
|
771
747
|
messages = linter.verify(code, configs, filename);
|
772
748
|
} finally {
|
773
|
-
Object.defineProperty(CodePath.prototype, "currentSegments", originalCurrentSegments);
|
774
749
|
SourceCode.prototype.applyInlineConfig = applyInlineConfig;
|
775
750
|
SourceCode.prototype.applyLanguageOptions = applyLanguageOptions;
|
776
751
|
SourceCode.prototype.finalize = finalize;
|
@@ -199,7 +199,7 @@ module.exports = {
|
|
199
199
|
: sourceCode.getLastToken(node),
|
200
200
|
penultimate = sourceCode.getTokenBefore(last),
|
201
201
|
firstElement = node.elements[0],
|
202
|
-
lastElement = node.elements
|
202
|
+
lastElement = node.elements.at(-1);
|
203
203
|
|
204
204
|
const openingBracketMustBeSpaced =
|
205
205
|
options.objectsInArraysException && isObjectType(firstElement) ||
|
@@ -147,7 +147,7 @@ module.exports = {
|
|
147
147
|
if (closestBlock.type === "BlockStatement") {
|
148
148
|
|
149
149
|
// find the last item in the block
|
150
|
-
const lastItem = closestBlock.body
|
150
|
+
const lastItem = closestBlock.body.at(-1);
|
151
151
|
|
152
152
|
// if the callback is the last thing in a block that might be ok
|
153
153
|
if (isCallbackExpression(node, lastItem)) {
|
@@ -168,7 +168,7 @@ module.exports = {
|
|
168
168
|
if (lastItem.type === "ReturnStatement") {
|
169
169
|
|
170
170
|
// but only if the callback is immediately before
|
171
|
-
if (isCallbackExpression(node, closestBlock.body
|
171
|
+
if (isCallbackExpression(node, closestBlock.body.at(-2))) {
|
172
172
|
return;
|
173
173
|
}
|
174
174
|
}
|
package/lib/rules/comma-style.js
CHANGED
@@ -66,7 +66,7 @@ module.exports = {
|
|
66
66
|
NewExpression: true
|
67
67
|
};
|
68
68
|
|
69
|
-
if (context.options.length === 2 && Object.
|
69
|
+
if (context.options.length === 2 && Object.hasOwn(context.options[1], "exceptions")) {
|
70
70
|
const keys = Object.keys(context.options[1].exceptions);
|
71
71
|
|
72
72
|
for (let i = 0; i < keys.length; i++) {
|
@@ -218,7 +218,7 @@ module.exports = {
|
|
218
218
|
|
219
219
|
previousItemToken = tokenAfterItem
|
220
220
|
? sourceCode.getTokenBefore(tokenAfterItem)
|
221
|
-
: sourceCode.ast.tokens
|
221
|
+
: sourceCode.ast.tokens.at(-1);
|
222
222
|
} else {
|
223
223
|
previousItemToken = currentItemToken;
|
224
224
|
}
|
package/lib/rules/complexity.js
CHANGED
@@ -64,7 +64,7 @@ module.exports = {
|
|
64
64
|
|
65
65
|
if (
|
66
66
|
typeof option === "object" &&
|
67
|
-
(Object.
|
67
|
+
(Object.hasOwn(option, "maximum") || Object.hasOwn(option, "max"))
|
68
68
|
) {
|
69
69
|
THRESHOLD = option.maximum || option.max;
|
70
70
|
} else if (typeof option === "number") {
|
@@ -109,7 +109,7 @@ function isPossibleConstructor(node) {
|
|
109
109
|
);
|
110
110
|
|
111
111
|
case "SequenceExpression": {
|
112
|
-
const lastExpression = node.expressions
|
112
|
+
const lastExpression = node.expressions.at(-1);
|
113
113
|
|
114
114
|
return isPossibleConstructor(lastExpression);
|
115
115
|
}
|
package/lib/rules/eol-last.js
CHANGED
@@ -45,7 +45,7 @@ module.exports = {
|
|
45
45
|
Program: function checkBadEOF(node) {
|
46
46
|
const sourceCode = context.sourceCode,
|
47
47
|
src = sourceCode.getText(),
|
48
|
-
lastLine = sourceCode.lines
|
48
|
+
lastLine = sourceCode.lines.at(-1),
|
49
49
|
location = {
|
50
50
|
column: lastLine.length,
|
51
51
|
line: sourceCode.lines.length
|
@@ -89,7 +89,7 @@ module.exports = {
|
|
89
89
|
});
|
90
90
|
} else if (mode === "never" && endsWithNewline) {
|
91
91
|
|
92
|
-
const secondLastLine = sourceCode.lines
|
92
|
+
const secondLastLine = sourceCode.lines.at(-2);
|
93
93
|
|
94
94
|
// File is newline-terminated, but shouldn't be
|
95
95
|
context.report({
|
@@ -218,7 +218,7 @@ module.exports = {
|
|
218
218
|
case "FunctionExpression": {
|
219
219
|
const leftParen = sourceCode.getFirstToken(node, astUtils.isOpeningParenToken);
|
220
220
|
const rightParen = node.params.length
|
221
|
-
? sourceCode.getTokenAfter(node.params
|
221
|
+
? sourceCode.getTokenAfter(node.params.at(-1), astUtils.isClosingParenToken)
|
222
222
|
: sourceCode.getTokenAfter(leftParen);
|
223
223
|
|
224
224
|
return { leftParen, rightParen };
|
@@ -234,7 +234,7 @@ module.exports = {
|
|
234
234
|
}
|
235
235
|
|
236
236
|
const rightParen = node.params.length
|
237
|
-
? sourceCode.getTokenAfter(node.params
|
237
|
+
? sourceCode.getTokenAfter(node.params.at(-1), astUtils.isClosingParenToken)
|
238
238
|
: sourceCode.getTokenAfter(firstToken);
|
239
239
|
|
240
240
|
return {
|
@@ -789,7 +789,7 @@ module.exports = {
|
|
789
789
|
if (elements.length > 0) {
|
790
790
|
|
791
791
|
// Skip last block line check if last item in same line
|
792
|
-
if (elements
|
792
|
+
if (elements.at(-1).loc.end.line === node.loc.end.line) {
|
793
793
|
return;
|
794
794
|
}
|
795
795
|
}
|
@@ -830,7 +830,7 @@ module.exports = {
|
|
830
830
|
}
|
831
831
|
|
832
832
|
let indent;
|
833
|
-
let nodesToCheck
|
833
|
+
let nodesToCheck;
|
834
834
|
|
835
835
|
/*
|
836
836
|
* For this statements we should check indent from statement beginning,
|
@@ -873,7 +873,7 @@ module.exports = {
|
|
873
873
|
*/
|
874
874
|
function filterOutSameLineVars(node) {
|
875
875
|
return node.declarations.reduce((finalCollection, elem) => {
|
876
|
-
const lastElem = finalCollection
|
876
|
+
const lastElem = finalCollection.at(-1);
|
877
877
|
|
878
878
|
if ((elem.loc.start.line !== node.loc.start.line && !lastElem) ||
|
879
879
|
(lastElem && lastElem.loc.start.line !== elem.loc.start.line)) {
|
@@ -892,7 +892,7 @@ module.exports = {
|
|
892
892
|
function checkIndentInVariableDeclarations(node) {
|
893
893
|
const elements = filterOutSameLineVars(node);
|
894
894
|
const nodeIndent = getNodeIndent(node).goodChar;
|
895
|
-
const lastElement = elements
|
895
|
+
const lastElement = elements.at(-1);
|
896
896
|
|
897
897
|
const elementsIndent = nodeIndent + indentSize * options.VariableDeclarator[node.kind];
|
898
898
|
|
@@ -999,7 +999,7 @@ module.exports = {
|
|
999
999
|
},
|
1000
1000
|
|
1001
1001
|
VariableDeclaration(node) {
|
1002
|
-
if (node.declarations
|
1002
|
+
if (node.declarations.at(-1).loc.start.line > node.declarations[0].loc.start.line) {
|
1003
1003
|
checkIndentInVariableDeclarations(node);
|
1004
1004
|
}
|
1005
1005
|
},
|