[ty] Fix stale semantic tokens after opening the same document with new content (#22414)

This commit is contained in:
Micha Reiser
2026-01-06 11:52:51 +01:00
committed by GitHub
parent a9e5246786
commit acbc83d6d2
3 changed files with 43 additions and 1 deletions

View File

@@ -526,7 +526,7 @@ impl VirtualFile {
}
/// Increments the revision of the underlying [`File`].
fn sync(&self, db: &mut dyn Db) {
pub fn sync(&self, db: &mut dyn Db) {
let file = self.0;
tracing::debug!("Updating the revision of `{}`", file.path(db));
let current_revision = file.revision(db);

View File

@@ -1575,6 +1575,9 @@ impl DocumentHandle {
{
db.project().remove_file(db, file);
}
// Bump the file's revision back to using the file system's revision.
file.sync(db);
} else {
// This can only fail when the path is a directory or it doesn't exists but the
// file should exists for this handler in this branch. This is because every
@@ -1598,6 +1601,8 @@ impl DocumentHandle {
if let Some(virtual_file) = db.files().try_virtual_file(virtual_path) {
db.project().close_file(db, virtual_file.file());
virtual_file.close(db);
// Bump the file's revision back to using the file system's revision.
virtual_file.sync(db);
} else {
tracing::warn!("Salsa virtual file does not exists for {}", virtual_path);
}

View File

@@ -70,3 +70,40 @@ fn multiline_token_client_supporting_multiline_tokens() -> Result<()> {
Ok(())
}
// Regression test for https://github.com/astral-sh/ty/issues/2346
#[test]
fn no_stale_tokens_after_opening_the_same_file_with_new_content() -> Result<()> {
let file_name = "src/foo";
let initial_content =
"def calculate_sum(a):\n # Version A: Basic math\n return a\n\nresult = calculate_sum(5)\n";
let mut server = TestServerBuilder::new()?
.enable_pull_diagnostics(true)
.enable_multiline_token_support(true)
.with_workspace(SystemPath::new("src"), None)?
.with_file(file_name, initial_content)?
.build()
.wait_until_workspaces_are_initialized();
server.open_text_document(file_name, initial_content, 0);
let initial_tokens = server
.semantic_tokens_full_request(&server.file_uri(file_name))
.unwrap();
server.close_text_document(file_name);
server.open_text_document(
file_name,
"# Version B: Basic greeting\ndef say_hello():\n print(\"Hello, World!\")\n\nsay_hello()\n",
0,
);
let new_tokens = server
.semantic_tokens_full_request(&server.file_uri(file_name))
.unwrap();
assert_ne!(initial_tokens, new_tokens);
Ok(())
}