Fix issue where renaming a file would not update imports in related files if they are not open (#36681)

Closes #34445

Now we open a multi-buffer consisting of buffers that have updated,
renamed file imports.

Only local is handled, for now.

Release Notes:

- Fixed an issue where renaming a file would not update imports in
related files if they are not already open.
This commit is contained in:
Smit Barmase 2025-08-21 20:19:17 +05:30 committed by GitHub
parent d9ea97ee9c
commit 697a39c251
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 87 additions and 11 deletions

View file

@ -88,9 +88,18 @@ pub enum BufferStoreEvent {
},
}
#[derive(Default, Debug)]
#[derive(Default, Debug, Clone)]
pub struct ProjectTransaction(pub HashMap<Entity<Buffer>, language::Transaction>);
impl PartialEq for ProjectTransaction {
fn eq(&self, other: &Self) -> bool {
self.0.len() == other.0.len()
&& self.0.iter().all(|(buffer, transaction)| {
other.0.get(buffer).is_some_and(|t| t.id == transaction.id)
})
}
}
impl EventEmitter<BufferStoreEvent> for BufferStore {}
impl RemoteBufferStore {

View file

@ -8762,7 +8762,7 @@ impl LspStore {
(root_path.join(&old_path), root_path.join(&new_path))
};
Self::will_rename_entry(
let _transaction = Self::will_rename_entry(
this.downgrade(),
worktree_id,
&old_abs_path,
@ -9224,7 +9224,7 @@ impl LspStore {
new_path: &Path,
is_dir: bool,
cx: AsyncApp,
) -> Task<()> {
) -> Task<ProjectTransaction> {
let old_uri = lsp::Url::from_file_path(old_path).ok().map(String::from);
let new_uri = lsp::Url::from_file_path(new_path).ok().map(String::from);
cx.spawn(async move |cx| {
@ -9257,7 +9257,7 @@ impl LspStore {
.log_err()
.flatten()?;
LocalLspStore::deserialize_workspace_edit(
let transaction = LocalLspStore::deserialize_workspace_edit(
this.upgrade()?,
edit,
false,
@ -9265,8 +9265,8 @@ impl LspStore {
cx,
)
.await
.ok();
Some(())
.ok()?;
Some(transaction)
}
});
tasks.push(apply_edit);
@ -9276,11 +9276,17 @@ impl LspStore {
})
.ok()
.flatten();
let mut merged_transaction = ProjectTransaction::default();
for task in tasks {
// Await on tasks sequentially so that the order of application of edits is deterministic
// (at least with regards to the order of registration of language servers)
task.await;
if let Some(transaction) = task.await {
for (buffer, buffer_transaction) in transaction.0 {
merged_transaction.0.insert(buffer, buffer_transaction);
}
}
}
merged_transaction
})
}

View file

@ -327,6 +327,7 @@ pub enum Event {
RevealInProjectPanel(ProjectEntryId),
SnippetEdit(BufferId, Vec<(lsp::Range, Snippet)>),
ExpandedAllForEntry(WorktreeId, ProjectEntryId),
EntryRenamed(ProjectTransaction),
AgentLocationChanged,
}
@ -2119,7 +2120,7 @@ impl Project {
let is_root_entry = self.entry_is_worktree_root(entry_id, cx);
let lsp_store = self.lsp_store().downgrade();
cx.spawn(async move |_, cx| {
cx.spawn(async move |project, cx| {
let (old_abs_path, new_abs_path) = {
let root_path = worktree.read_with(cx, |this, _| this.abs_path())?;
let new_abs_path = if is_root_entry {
@ -2129,7 +2130,7 @@ impl Project {
};
(root_path.join(&old_path), new_abs_path)
};
LspStore::will_rename_entry(
let transaction = LspStore::will_rename_entry(
lsp_store.clone(),
worktree_id,
&old_abs_path,
@ -2145,6 +2146,12 @@ impl Project {
})?
.await?;
project
.update(cx, |_, cx| {
cx.emit(Event::EntryRenamed(transaction));
})
.ok();
lsp_store
.read_with(cx, |this, _| {
this.did_rename_entry(worktree_id, &old_abs_path, &new_abs_path, is_dir);