ESLint v10 support#3230
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3230 +/- ##
===========================================
- Coverage 95.82% 80.95% -14.88%
===========================================
Files 83 97 +14
Lines 3741 4438 +697
Branches 1355 1535 +180
===========================================
+ Hits 3585 3593 +8
- Misses 156 845 +689 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
@rasmi Do you want to disclose your usage of LLMs to generate this PR description and/or PR, which @ljharb objected to in another repo jsx-eslint/eslint-plugin-jsx-a11y#1077 ? |
|
Was not aware, thanks @StephanTLavavej! It is a bit disappointing, as I spent a few hours of my day working on this, even with LLM tools. I will close this PR regardless out of respect for the maintainer (I just want to make sure the tests pass for my own edification). |
efa4b8b to
069a70f
Compare
|
Just curious (and with all respect), what is the real issue of LLM-generated code? What matters is the code, right? If the PR is too big, or too hard to review, we could just improve that? |
|
@StephanTLavavej please do not take it upon yourself to act as if you're a maintainer. Each project can have different policies regardless of who's maintaining them. Please do not attempt to police projects you aren't even a significant contributor to. @rasmi if you're using an LLM to automate applying changes you're writing, I'm fine with that - however if you're just prompting one to "add eslint v10 support", i have my own LLM subscription for that kind of thing :-) @dirkluijk no, "what matters" has never been, and never will be, just "the code". Any code contribution represents a legal assignment of rights, as well as an eternal maintenance burden on that code, and as such, the human contributor is an important factor. |
|
@ljharb -- point well-taken! I did go through a more rigorous process here -- it really did take me hours of focused work, thinking about implementation approaches, iterating, fixing tests, etc. It is not my intention to submit slop, I wanted to submit a PR that I hoped would meet the standard of the library, at least as a first pass. I lack decision-making insight/context on things like "Is it okay to just use glob, if not let's do a custom file search" and "exactly how should node vs. eslint-parser vs. core library version compatibility be handled" -- but this is what the review process is for! I also understand that big changes like this may be simpler for the maintainer to just take on directly, as you have all the proper context and expertise on all the nuances of the library and ecosystem, to say the least. Apologies again, I didn't mean to burden you at all, I know it is hard to maintain core libraries like this. Please do with this what you wish! |
|
What is the current status of this PR? |
|
Hi @ljharb -- let me know if you have any feedback / next steps on this that I can address. Sorry to ping you, but there is quite a crowd on this PR and #3227. If the issue is codecoverage, I can add new test coverage. I think my main concern was whether some of the design decisions are appropriate for the project. (just rebasing onto main & force-pushing now) |
|
#3237 should fix the tests currently failing in |
Move the `getTokenOrComment{Before,After}`
feature-detection shims out of the rule and into
`src/core/getTokenOrComment.js` so both the legacy and the
`getToken{Before,After}({ includeComments: true })`
branches can be unit-tested directly.
They cannot be exported from the rule module:
the plugin loads rules via `require`,
which only yields the rule object while the file has a single default export.
…fallbacks
Exercise both branches of the `getTokenOrComment{Before,After}` shims,
and the `listFilesToProcess` fallback to
`listFilesWithNodeFs` when the legacy `glob-utils` module is no longer exported
(`ERR_PACKAGE_PATH_NOT_EXPORTED`, eslint 10)
in addition to the existing `MODULE_NOT_FOUND` case.
|
@ljharb I opened rasmi/eslint-plugin-import#1 against @rasmi's |
`v3.1.5` is the last v3 release. v4 made the upload token effectively required and broke tokenless coverage uploads from fork PRs of public repos, which is the reason this action was pinned back. v5 restored reliable tokenless fork-PR uploads; v7 is the current release. Fork PRs cannot read repository secrets, so they have always relied on tokenless uploads. Against the sunset v3 endpoint those uploads were frequently rate-limited/dropped, so version-specific code covered only by certain matrix jobs appeared uncovered in the merged head report (~19 upload sessions on the head vs ~40 on the base in import-js#3230). Upgrading makes uploads reliable without lowering any coverage target or adding `flags`/`ignore`.
…branches Exercise both the modern (ESLint 8+) and the deprecated fallback branch of each compat shim - `getSourceCode`, `getScope`, `getAncestors`, `getDeclaredVariables`, `getFilename`, and `getPhysicalFilename` - with stub contexts. These modern branches were previously only hit incidentally by rule tests on particular eslint versions.
A glob whose base directory does not exist now exercises the `readdirSync` failure branch.
|
Ok, this one should clear that -0.04%. |
|
Codecov being codecov again. Failed uploads. |
|
Codecov isn't a blocker, don't worry. |
|
Thank you @ljharb |
`v3.1.5` is the last v3 release. v4 made the upload token effectively required and broke tokenless coverage uploads from fork PRs of public repos, which is the reason this action was pinned back. v5 restored reliable tokenless fork-PR uploads; v7 is the current release. Fork PRs cannot read repository secrets, so they have always relied on tokenless uploads. Against the sunset v3 endpoint those uploads were frequently rate-limited/dropped, so version-specific code covered only by certain matrix jobs appeared uncovered in the merged head report (~19 upload sessions on the head vs ~40 on the base in import-js#3230). Upgrading makes uploads reliable without lowering any coverage target or adding `flags`/`ignore`.
|
And thanks @captaindonald! |
|
Thank you for this! |
Summary
Add ESLint v10 support while maintaining backward compatibility with ESLint v2–v9. The v10 compat changes in shipped code use feature detection (e.g. checking if
context.languageOptionsexists) rather than version checks.Closes:
import/no-unused-modulesonly works in flat config if an.eslintrcfile exists as well #3079Split out into separate PRs (independent / pre-existing issues revealed during v10 update; this branch rebases onto them and becomes v10-only):
export * as nsre-exports under modern parsers #3250: for issues [export] incorrect report onexport * as#2002,export * as nsfalse positive on import/named rule #1883, [import/export] False "Multiple exports of name" error when two "export * as ..." contain same name. #1834, import/named and import/namespace errors after upgrading Babel #1845, False "Multiple exports of name" error when two "export * as ..." contain same name [import/export] #2289What changed
Removed API replacements
ESLint v10 removed several deprecated
contextproperties andSourceCodemethods. Each call site now feature-detects the new API and falls back to the old one:context.parserOptions→context.languageOptions.parserOptions(affectssourceType.js,childContext.js,typescript.js,scc.js,parse.js)context.parserPath→context.languageOptionsused for cache hashing instead (scc.js)context.getPhysicalFilename()→context.physicalFilenameproperty (contextCompat.js)context.getScope()→ already had a compat wrapper, but one call site indeclaredScope.jsbypassed it — now fixedsourceCode.getTokenOrCommentAfter/Before()→sourceCode.getTokenAfter/Before(node, { includeComments: true })(order.js)no-unused-modulesfile enumeration fallbackESLint v10 removed
FileEnumeratorand the internalglob-utilsmodule. The existing cascade (FileEnumerator→ legacyglob-utils) now has a third tier: a Node.jsfs+minimatchfallback that walks directories and matches globs.MODULE_NOT_FOUNDorERR_PACKAGE_PATH_NOT_EXPORTEDminimatchandis-glob(existing direct dependencies).eslintrc) sinceFileEnumeratoris no longer used. The issue remains on v9.Test infrastructure (test files only)
On v10, the unmaintained
babel-eslint(Babel 6) is replaced with@babel/eslint-parserv8 for test coverage. This restores ~475 babel-related tests that would otherwise be skipped on v10.FlatCompatRuleTesterextended to auto-inject@babel/eslint-parserconfig (requireConfigFile: false,babelrc: false, syntax plugins) and handle v10 RuleTester strictnessno-duplicatestests skipped: duplicate import identifiers correctly rejected by@babel/eslint-parser@typescript-eslint/parserv8 (import type Default, { Named }removed in TS 5.0)Dependency changes
eslint|| ^10added to peerDeps and devDepsv10-specific parser deps are installed via
dep-time-travel.sh(not in devDeps) to avoid peer dep conflicts withtypescript@4.5.5duringnpm install:@typescript-eslint/parser@8— on all ESLint 10 Node versions-
@angular-eslint/template-parser@21— on all ESLint 10 Node versions (v13 does not support ESLint 10)@babel/eslint-parser@8+@babel/core@8(ESM, RC) — on Node >= 20^20.19.0 || >=22.12.0; v7 will not get ESLint 10 support). Babel tests are skipped; all other tests run.CI changes
eslint-8+.yml: added ESLint 10 to the matrix, excluded Node < 18dep-time-travel.sh: installs v10-specific parser deps (@typescript-eslint/parser@8and@angular-eslint/template-parser@21on all nodes,@babel/eslint-parser@8on Node >= 20 only)