Change Request: Support "cross-file" linting
- Dominant language
- JavaScript
- Stars
- 348
- Forks
- 51
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 11
Description
### Which packages would you like to change?
- [ ] `@eslint/compat`
- [ ] `@eslint/config-array`
- [ ] `@eslint/config-helpers`
- [x] `@eslint/core`
- [ ] `@eslint/mcp`
- [ ] `@eslint/migrate-config`
- [ ] `@eslint/object-schema`
- [ ] `@eslint/plugin-kit`
### What problem do you want to solve?
"Cross-file" or "multi-file" linting is an increasingly common need in many lint plugins. Two common user needs are from:
* Cross file types like [typescript-eslint](https://typescript-eslint.io)'s [typed linting](https://typescript-eslint.io/getting-started/typed-linting).
* Import analysis in plugins like [`eslint-plugin-import`](https://github.com/import-js/eslint-plugin-import) and [`eslint-plugin-import-x`](https://www.npmjs.com/package/eslint-plugin-import-x)
ESLint today does not have any native concepts of cross-file dependencies, stateful parsing, or type information. It does not provide APIs for them. As a result, userland plugins have needed to put cross-file parsing into _parsers_ such as [`@typescript-eslint/parser`](https://typescript-eslint.io/packages/parser). This is the only way to get it to work in ESLint right now, but is problematic:
* ESLint's parsers are intended to be _isolated_ and _stateless_. Using them for _contextually aware_ and/or _stateful_ logic breaks that paradigm.
* ESLint's `--cache` is fundamentally unreliable when users opt into any form of cross-file linting, as cache invalidation does not account for cross-file information.
* Parsers don't receive information like a full list of files, what form of session ESLint is being run in, etc. - which would be useful for optimizing cross-file things.
* (From my anecdotal recollection) ESLint's `--concurrency` often ends up being slower on large codebases using typed linting, as each thread/worker instantiates TypeScript type services that end up significantly overlapping in functionality
### What do you think is the correct solution?
I personally have been advocating for a two-step approach:
1. Since users are using plugins for cross-file linting _now_ (and have been since at least typescript-eslint was introduced in 2019), adding in rudimentary stateful information to parsers.
2. In the big ESLint rewrite, add a more native concept of a stateful entity. Something that has setup and teardown phases, knows the full list of files, and can instantiate services such as a module dependency graph or a type-checker.
The feedback we've gotten from the TSC has been that only the latter is desirable.
### Participation
- [x] I am willing to submit a pull request for this change.
### Additional comments
I asked about this internally and was suggested by @nzakas to post an issue. This is that issue! 🙂 Is there other information that would be useful for me to file that isn't in the major past discussions? For quick reference:
* https://github.com/eslint/eslint/discussions/16557: past discussion opening up this rewrite repo & touching on points such as making ESLint type-aware and/or project-aware
* https://github.com/eslint/eslint/discussions/16819: further discussion on these topics
* https://github.com/eslint/rfcs/pull/102: has a lot of links & text explaining needs around session information
* https://github.com/typescript-eslint/typescript-eslint/issues/11677: further explains the typescript-eslint perspective & list of needs blocked on stateful services
Terminology aside: I've personally been calling this _"cross-file"_ linting to convey that it uses an understanding of code built up across-files. "Multi-file" makes me think the linter is reporting on multiple files at once, or that lint rules are targeted to multiple files at a time. I'm not intending to suggest completely redesigning the core concept of "each rule looks at a file at a time". Just that the information they use on each file is more informed.
Contributor guide
Assessment
This issue has not been assessed yet.