[ty] Support diagnostics in newly created files inside neovim#23095
[ty] Support diagnostics in newly created files inside neovim#23095BurntSushi merged 1 commit intomainfrom
Conversation
|
Demo: 2026-02-05T12.16.18-05.00.mp4 |
Typing conformance resultsNo changes detected ✅ |
|
I think this is only true when invoked from the command-line because the language server uses
This is because open files which doesn't exists on disk is a virtual file but it seems that Neovim seems to be using a regular Virtual files are indicated with |
I sent you some messages, but I don't think this is true. From neovim at least, I actually can't make the server operate in Still though, even if |
b7daafd to
d2e4e63
Compare
crates/ty_project/src/db/changes.rs
Outdated
| if self.system().is_file(&path) | ||
| && project.is_file_included(self, &path) | ||
| && let Some(file) = self.files().try_system(self, &path) | ||
| && !project.files(self).contains(&file) |
There was a problem hiding this comment.
Can we add a test case for this scenario (e2e preferably)?
There was a problem hiding this comment.
Yes! I added three. :-)
I think this might also fix #15392?
There was a problem hiding this comment.
That issue is specific to the Ruff server so it might require a different solution as the architecture differs.
d2e4e63 to
3b9de75
Compare
|
This fixes an issue where one could open a new Python file in neovim,
save it, write some code but not get any diagnostics from ty.
There are two separate issues here.
One is that we currently use `CheckMode::AllFiles` by default and this
_specifically_ ignores opened files that haven't been picked up as a
project file on disk yet. This PR does not address that issue. Notably,
we do have a `CheckMode::OpenFiles`, but I'm currently not clear on why
`AllFiles` explicitly ignores open files.
The second issue is that even after the file is saved on disk, our LSP
doesn't add it to its internal project state. Such that once the client
asks for diagnostics, we return nothing. This seems like a state
synchronization issue, because if you create a second new file, then
this will force directory re-scanning and cause the LSP to pick up the
first file created. That is, when a file is "opened," ty will do a
directory scan. But if the opened file doesn't actually exist on disk
yet, it won't see it.
The third issue is that `workspace/didChangeWatchedFiles` is turned off
by default in neovim's LSP client on Linux for performance reasons. It
can be turned back on with this config:
```lua
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities.workspace.didChangeWatchedFiles.dynamicRegistration = true
vim.lsp.config('ty', {
capabilities = capabilities,
})
vim.lsp.enable('ty')
```
Once enabled, everything _almost_ works, except that neovim will
sometimes send a CHANGE event without a corresponding CREATED event.
This also messes up our state handling because a CHANGE event never
results in rescanning the directory to pick up new files.
This PR addresses this problem by always checking the open file
set instead of relying on our virtual path detection to always be
correct. Notably, neovim does not follow the LSP convention of using an
`untitled://...` scheme for documents that do not yet exist on disk,
but we rely on that convention to determine whether a file is virtual
or not.
Fixes astral-sh/ty#2616, Ref #15392
ea48e1c to
a7198dd
Compare
Memory usage reportMemory usage unchanged ✅ |
|
I'm going to bring this in. We can revisit the wisdom of always checking the open file set if issues come up. I think it's probably a better change than what I had before, which was trying to interpret CHANGE events as CREATION events in some circumstances. |
This fixes an issue where one could open a new Python file in neovim,
save it, write some code but not get any diagnostics from ty.
There are two separate issues here.
One is that we currently use
CheckMode::AllFilesby default and thisspecifically ignores opened files that haven't been picked up as a
project file on disk yet. This PR does not address that issue. Notably,
we do have a
CheckMode::OpenFiles, but I'm currently not clear on whyAllFilesexplicitly ignores open files.The second issue is that even after the file is saved on disk, our LSP
doesn't add it to its internal project state. Such that once the client
asks for diagnostics, we return nothing. This seems like a state
synchronization issue, because if you create a second new file, then
this will force directory re-scanning and cause the LSP to pick up the
first file created. That is, when a file is "opened," ty will do a
directory scan. But if the opened file doesn't actually exist on disk
yet, it won't see it.
The third issue is that
workspace/didChangeWatchedFilesis turned offby default in neovim's LSP client on Linux for performance reasons. It
can be turned back on with this config:
Once enabled, everything almost works, except that neovim will
sometimes send a CHANGE event without a corresponding CREATED event.
This also messes up our state handling because a CHANGE event never
results in rescanning the directory to pick up new files.
This PR attempts to address this problem somewhat narrowly by adding
some logic that will force a directory rescan in response to a CHANGE
event. Specifically, when all of the following is true:
Fileinside our salsa DB.project.files()doesn't contain it yet.This, in combination with enabling
workspace/didChangeWatchedFiles,causes ty to pick up newly added and saved to disk files.
Fixes astral-sh/ty#2616