Skip to content

Commit bd0901b

Browse files
authored
Support ESLint 10 (#2823)
1 parent ab8970e commit bd0901b

13 files changed

Lines changed: 195 additions & 36 deletions

.github/workflows/main.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
- uses: actions/setup-node@v4
3030
with:
3131
node-version: ${{ matrix.node-version }}
32-
- run: npm install
32+
- run: npm install --legacy-peer-deps
3333
- run: npx c8 ava
3434
- uses: codecov/codecov-action@v5
3535
with:
@@ -42,14 +42,14 @@ jobs:
4242
steps:
4343
- uses: actions/checkout@v4
4444
- uses: actions/setup-node@v4
45-
- run: npm install
45+
- run: npm install --legacy-peer-deps
4646
- run: npm run lint
4747
run-rules-on-codebase:
4848
runs-on: ubuntu-latest
4949
steps:
5050
- uses: actions/checkout@v4
5151
- uses: actions/setup-node@v4
52-
- run: npm install
52+
- run: npm install --legacy-peer-deps
5353
- run: npm run run-rules-on-codebase
5454
integration:
5555
name: Integration test (${{ matrix.group }})
@@ -72,5 +72,5 @@ jobs:
7272
steps:
7373
- uses: actions/checkout@v4
7474
- uses: actions/setup-node@v4
75-
- run: npm install
75+
- run: npm install --legacy-peer-deps
7676
- run: npm run integration -- --group ${{ matrix.group }}

.github/workflows/smoke-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
steps:
1212
- uses: actions/checkout@v4
1313
- uses: actions/setup-node@v4
14-
- run: npm install
14+
- run: npm install --legacy-peer-deps
1515
- uses: AriPerkkio/eslint-remote-tester-run-action@v5
1616
with:
1717
issue-title: "Results of weekly scheduled smoke test"

.github/workflows/update-snapshots.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
with:
1616
# Locked due to the difference of `zlib.gzipSync()` between Node.js versions
1717
node-version: 24
18-
- run: npm install
18+
- run: npm install --legacy-peer-deps
1919
- run: npm run lint
2020
- run: rm -rf test/snapshots
2121
# Force update snapshots, https://github.com/avajs/ava/discussions/2754

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
"ava": "^6.4.1",
8686
"c8": "^10.1.3",
8787
"enquirer": "^2.4.1",
88-
"eslint": "^9.38.0",
88+
"eslint": "^10.0.0-beta.0",
8989
"eslint-ava-rule-tester": "^5.0.1",
9090
"eslint-config-xo": "^0.49.0",
9191
"eslint-doc-generator": "^2.3.0",
@@ -109,7 +109,7 @@
109109
"yaml": "^2.8.1"
110110
},
111111
"peerDependencies": {
112-
"eslint": ">=9.38.0"
112+
"eslint": ">=9.38.0 || >=10.0.0-0"
113113
},
114114
"ava": {
115115
"files": [

rules/custom-error-definition.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import {upperFirst} from './utils/index.js';
1+
import {
2+
upperFirst,
3+
getParenthesizedText,
4+
} from './utils/index.js';
25

36
const MESSAGE_ID_INVALID_EXPORT = 'invalidExport';
47
const messages = {
@@ -121,7 +124,12 @@ function * customErrorDefinition(context, node) {
121124
if (superExpression.expression.arguments.length === 0) {
122125
const rhs = expression.expression.right;
123126
const [start] = sourceCode.getRange(superExpression);
124-
yield fixer.insertTextAfterRange([start, start + 6], rhs.raw || rhs.name);
127+
// This part crashes on ESLint 10, but it's still not correct.
128+
// There can be spaces, comments after `super`
129+
yield fixer.insertTextAfterRange(
130+
[start, start + 6],
131+
getParenthesizedText(rhs, context),
132+
);
125133
}
126134

127135
const start = messageExpressionIndex === 0

rules/prefer-string-slice.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ function * fixSubstrArguments({node, fixer, context, abort}) {
4848
}
4949

5050
if (typeof getNumericValue(secondArgument) === 'number') {
51-
yield replaceSecondArgument(Math.max(0, getNumericValue(secondArgument)));
51+
yield replaceSecondArgument(String(Math.max(0, getNumericValue(secondArgument))));
5252
return;
5353
}
5454

@@ -58,7 +58,7 @@ function * fixSubstrArguments({node, fixer, context, abort}) {
5858
}
5959

6060
if (argumentNodes.every(node => isNumericLiteral(node))) {
61-
yield replaceSecondArgument(firstArgument.value + secondArgument.value);
61+
yield replaceSecondArgument(String(firstArgument.value + secondArgument.value));
6262
return;
6363
}
6464

@@ -78,7 +78,7 @@ function * fixSubstringArguments({node, fixer, context, abort}) {
7878
}
7979

8080
if (firstNumber !== undefined) {
81-
yield replaceFirstArgument(Math.max(0, firstNumber));
81+
yield replaceFirstArgument(String(Math.max(0, firstNumber)));
8282
return;
8383
}
8484

@@ -99,18 +99,18 @@ function * fixSubstringArguments({node, fixer, context, abort}) {
9999
}
100100

101101
if (argumentsValue[0] !== firstNumber) {
102-
yield replaceFirstArgument(argumentsValue[0]);
102+
yield replaceFirstArgument(String(argumentsValue[0]));
103103
}
104104

105105
if (argumentsValue[1] !== secondNumber) {
106-
yield replaceSecondArgument(argumentsValue[1]);
106+
yield replaceSecondArgument(String(argumentsValue[1]));
107107
}
108108

109109
return;
110110
}
111111

112112
if (firstNumber === 0 || secondNumber === 0) {
113-
yield replaceFirstArgument(0);
113+
yield replaceFirstArgument('0');
114114
yield replaceSecondArgument(`Math.max(0, ${firstNumber === 0 ? secondArgumentText : firstArgumentText})`);
115115
return;
116116
}

scripts/parsers.js

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
Based on https://github.com/eslint/eslint/pull/20132
3+
Workaround for https://github.com/typescript-eslint/typescript-eslint/issues/11762
4+
*/
5+
6+
import {Variable} from 'eslint-scope';
7+
import typescriptEslintParserOriginal from '@typescript-eslint/parser';
8+
import babelEslintParserOriginal from '@babel/eslint-parser';
9+
import vueEslintParserOriginal from 'vue-eslint-parser';
10+
11+
function addGlobals(names) {
12+
const globalScope = this.scopes[0];
13+
for (const name of names) {
14+
let variable = globalScope.set.get(name);
15+
16+
if (variable) {
17+
continue;
18+
}
19+
20+
variable = new Variable(name, globalScope);
21+
22+
globalScope.variables.push(variable);
23+
globalScope.set.set(name, variable);
24+
}
25+
26+
/*
27+
* "through" contains all references which definitions cannot be found.
28+
* Since we augment the global scope we need to update references
29+
* and remove the ones that were added.
30+
*
31+
* Also, typescript-eslint's scope manager doesn't resolve references
32+
* to global `var` and `function` variables, so we'll resolve _all_
33+
* references to variables that exist in the global scope.
34+
*/
35+
globalScope.through = globalScope.through.filter(reference => {
36+
const {name} = reference.identifier;
37+
const variable = globalScope.set.get(name);
38+
39+
if (variable) {
40+
/*
41+
* Links the variable and the reference.
42+
* And this reference is removed from `Scope#through`.
43+
*/
44+
reference.resolved = variable;
45+
variable.references.push(reference);
46+
47+
return false;
48+
}
49+
50+
return true;
51+
});
52+
53+
/*
54+
* "implicit" contains information about implicit global variables (those created
55+
* implicitly by assigning values to undeclared variables in non-strict code).
56+
* Since we augment the global scope, we need to remove the ones that were added.
57+
*/
58+
const {implicit} = globalScope;
59+
implicit.variables = implicit.variables.filter(variable => {
60+
const {name} = variable;
61+
if (globalScope.set.has(name)) {
62+
implicit.set.delete(name);
63+
return false;
64+
}
65+
66+
return true;
67+
});
68+
69+
// Typescript-eslint's scope manager doesn't produce "implicit.left"
70+
}
71+
72+
function fixParse(parse) {
73+
return function parseForESLint(...arguments_) {
74+
const result = parse(...arguments_);
75+
76+
if (result.scopeManager) {
77+
result.scopeManager.addGlobals ??= addGlobals;
78+
}
79+
80+
return result;
81+
};
82+
}
83+
84+
export const typescriptEslintParser = {
85+
...typescriptEslintParserOriginal,
86+
parseForESLint: fixParse(typescriptEslintParserOriginal.parseForESLint),
87+
};
88+
89+
export const babelEslintParser = {
90+
...babelEslintParserOriginal,
91+
parseForESLint: fixParse(babelEslintParserOriginal.parseForESLint),
92+
};
93+
94+
export const vueEslintParser = {
95+
...vueEslintParserOriginal,
96+
parseForESLint: fixParse(vueEslintParserOriginal.parseForESLint),
97+
};

test/custom-error-definition.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,28 @@ const tests = {
457457
`,
458458
errors: [passMessageToSuperError],
459459
},
460+
{
461+
code: outdent`
462+
class FooError extends Error {
463+
constructor() {
464+
super();
465+
this.message = foo.error;
466+
this.name = 'FooError';
467+
}
468+
}
469+
`,
470+
output: outdent`
471+
class FooError extends Error {
472+
constructor() {
473+
super(foo.error);
474+
this.name = 'FooError';
475+
}
476+
}
477+
`,
478+
errors: [
479+
passMessageToSuperError,
480+
],
481+
},
460482
],
461483
};
462484

test/expiring-todo-comments.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ test({
5555
'// FIXME [2200-12-12] (lubien): Too long... Can you feel it?',
5656
{
5757
code: '// Expire Condition [2200-12-12]: new term name',
58-
errors: [],
5958
options: [{terms: ['Expire Condition']}],
6059
},
6160
'// Expire Condition [2000-01-01]: new term name',
@@ -80,19 +79,15 @@ test({
8079
*/`,
8180
{
8281
code: '// TODO',
83-
errors: [],
8482
},
8583
{
8684
code: '// TODO [invalid]',
87-
errors: [],
8885
},
8986
{
9087
code: '// TODO [] might have [some] that [try [to trick] me]',
91-
errors: [],
9288
},
9389
{
9490
code: '// TODO [but [it will]] [fallback] [[[ to the default ]]] rule [[',
95-
errors: [],
9691
},
9792
{
9893
code: '// TODO ISSUE-123 fix later',

test/integration/projects.js

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,13 @@ export default [
3838
'test-tap/fixture/report/edgecases/ast-syntax-error.cjs',
3939
],
4040
},
41-
'https://github.com/chalk/chalk',
41+
{
42+
repository: 'https://github.com/chalk/chalk',
43+
ignore: [
44+
// Uses `/* eslint-env */`
45+
'source/vendor/supports-color/browser.js',
46+
],
47+
},
4248
'https://github.com/chalk/wrap-ansi',
4349
'https://github.com/sindresorhus/np',
4450
'https://github.com/sindresorhus/ora',
@@ -113,7 +119,15 @@ export default [
113119
'importAssertions',
114120
],
115121
},
116-
'https://github.com/ReactTraining/react-router',
122+
{
123+
repository: 'https://github.com/ReactTraining/react-router',
124+
ignore: [
125+
// Uses `/* eslint-env */`
126+
'packages/react-router/lib/dom/node-main.js',
127+
'packages/react-router/node-main-dom-export.js',
128+
'packages/react-router/node-main.js',
129+
],
130+
},
117131
// #902
118132
{
119133
repository: 'https://github.com/reakit/reakit',
@@ -146,6 +160,13 @@ export default [
146160
{
147161
repository: 'https://github.com/TheThingsNetwork/lorawan-stack',
148162
babelPlugins: ['decorators'],
163+
ignore: [
164+
// Uses `/* eslint-env */`
165+
'config/storybook/webpack.config.js',
166+
'config/webpack.config.babel.js',
167+
'config/webpack.dll.babel.js',
168+
'pkg/webui/lib/get-by-path_test.js',
169+
],
149170
},
150171
'https://github.com/zloirock/core-js',
151172
{
@@ -184,6 +205,10 @@ export default [
184205
'test/**',
185206
'**/tests/**',
186207
'**/compiled/**',
208+
209+
// Uses `/* eslint-env */`
210+
'packages/next/src/server/lib/router-utils/decode-path-params.test.ts',
211+
'packages/next/src/server/node-polyfill-crypto.test.ts',
187212
],
188213
},
189214
// #903
@@ -204,6 +229,10 @@ export default [
204229

205230
// Global return
206231
'scripts/cypress.js',
232+
233+
// Uses `/* eslint-env */`
234+
'packages/charts/chart-web-components/scripts/e2e.js',
235+
'packages/web-components/scripts/e2e.js',
207236
],
208237
},
209238
{
@@ -236,6 +265,8 @@ export default [
236265
'src/vs/platform/files/test/node/fixtures/**',
237266
'src/vs/workbench/services/search/test/node/fixtures/examples/**',
238267
'extensions/vscode-colorize-perf-tests/test/**',
268+
// Uses `/* eslint-env */`
269+
'test/unit/electron/renderer.js',
239270
],
240271
},
241272
].flatMap((projectOrProjects, index) =>

0 commit comments

Comments
 (0)