-
Notifications
You must be signed in to change notification settings - Fork 341
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ESLint does not re-compute cross-file information on file changes #1774
Comments
@JoshuaKGoldberg thanks for reaching out to me.
How does that re-parse API look like. What I would like to avoid is that the ESLint server needs to know about dependencies in TS files. |
And would there be API for me to find out (on the ESLint level) if the parser has TS type information loaded to avoid this in cases where it is not necessary. |
Looking at
Yeah the difficulty there is in theory any file can cause this issue. A
I can think of a few directions...
|
A reasonable approach would be like this:
A "correct" approach would be like this:
This would be the most effective implementation since it would only revalidate files if the TS program has changed. Let me know if you think the second approach would be doable for the plugin. |
Theoretically yes: the resolved ESLint But that wouldn't fix things for the users of other multi-file-linting parsers mentioned in #1774 (comment). That list is non-exhaustive: I also remembered
Would this be noticeably better than the existing Restart ESLint Server action? That one is pretty fast in my experience. And most of the slowness folks experience from expensive linting occurs from out-of-file analysis that would happen in both commands.
I think this watch mode is theoretically doable. Two difficulties:
I suppose this is possible, with more of the same two difficulties noted in the previous session. cc @bradzacher - who has often had a superset of my knowledge about these workings. |
This is relevant to eslint-plugin-import, since editing any file could cause any other file to become invalid. Tightly integrating the concept of “vscode” or “a language server” into individual eslint plugins (that shouldn’t ever need to be aware of such concepts) doesn’t seem like a viable or maintainable approach to me, altho ofc I’m willing to make changes if that would solve the problem. |
We can build and maintain a util for you (eg pass a config and we return a boolean) to avoid you relying on our implementation details. That being said - as Jordan mentioned there are more usecases for "refresh" beyond type info in the eslint ecosystem so tying it to one subset is probs more limited than we'd ultimately want. FWIW I've asked eslint for a way to register file dependency at lint time and the response was essentially "not until we rewrite eslint". So we can either build a paradigm outside their APIs, or we can wait (probably another few years). The former is burden for us (or mostly the IDE extensions), yes, but would fix the DevX that everyone currently hates and complains about to us - a lot. |
This wouldn't help us. We already do this really - just using the lower-level APIs. But we don't attach file watchers because eslint provides no mechanism for us to know when the "lint run is done" - so we don't know when to detach the watchers and if we don't do that the ESLint CLI never exits. But regardless - the server in watch mode doesn't really provide us with any wins because we don't coordinate the lint run - eslint does. Us recalculating types eagerly doesn't do anything unless a lint run is done. Once the user saves a file it'll trigger a fresh lint run on the file which will make eslint call us and we'll recalculate the types. After that if you "re lint all open files" they should be mostly free to lint because we don't need to recalculate types. |
Thanks for all the comments. Reading through them shows that there isn't an easy solution to fix this since none of the participants has enough information right now to do the proper calculation whether a reparse is necessary or not. To summarize things:
I also understand that not every rule want to build a dependency tree and have file watchers to determine this itself. Since VS Code as a file change and watcher capabilities it would be OK for me if the extension does the re-linting however I would like to request some more support from ESLint as well. Ideal would a solution where the ESLint extension could find out for every rule if it has inter file dependencies or not. Does anyone know if something is possible today? I haven't found an API to get to a rule object. If something like this is not possible I think we need to talk to the ESLint maintainers to see if something like this could be added. What I could do is the following:
Any additional thought? |
In terms of eslint building something - we may be on our own for now, at least until eslint completes it's rewrite. Based on past discussions it sounds like they don't want to make any changes to the core until the rewrite. Refs:
|
I'd be okay with either of these. Though the latter wouldn't clear the problems pane - at least it would clear as soon as the user focuses the file.
If we're talking re-linting open files I'd have thought most user sessions would have at most a dozen files up at any given time? (I have no idea - pulling a number out by butt based on how I use it) so a full session lint should be fast - esp considering most files don't need type info re-calculated and just need the lint rules to run. What about if we did it just asynchronously on save instead? Is that doable? Idk if vscode exposes the signals to do that. |
VS Code has auto save and it is on for a lot of users. For them this would result in some performance problems as well. |
Could we do a "throttle" on the event? If we pair that with "re lint file on focus if a change has occurred since the file was last linted" then we could have good coverage of everything without being too expensive:
The trade-off here is implementation complexity, of course. If we could make the extension aware of the explicit dependencies of a given file then we'd be well off - though IIRC it's actually pretty hard to get this information performantly out of the |
There's a known issue with typescript-eslint that modifying one file doesn't impact the view of that file's types seen by other files:
Copying that issue's explanation here:
@typescript-eslint/parser
sets up a TypeScript program behind-the-scenes when it parses files. The program for a file is later made onESLintUtils.getParserServicescontext).program
. This is documented in Custom Rules > Typed Rules. That program is what's used for type information in typed lint rules.One known issue with the parser-generating-type-information strategy is that programs are only recreated when ESLint re-parses. I'm not sure how best to solve this on the editor side, so asking for help here 🙂. Would it be reasonable for vscode-eslint to trigger an ESLint re-parse whenever a file is modified on disk?
Edit: summarizing discussion below, this is not limited to just typescript-eslint's type-checked rules. Any lint rule that uses cross-file information is impacted. That includes plugins like
eslint-plugin-import
/eslint-plugin-import-x
.The text was updated successfully, but these errors were encountered: