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:
parent
d9ea97ee9c
commit
697a39c251
4 changed files with 87 additions and 11 deletions
|
@ -1900,6 +1900,60 @@ impl Editor {
|
|||
editor.update_lsp_data(false, Some(*buffer_id), window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
project::Event::EntryRenamed(transaction) => {
|
||||
let Some(workspace) = editor.workspace() else {
|
||||
return;
|
||||
};
|
||||
let Some(active_editor) = workspace.read(cx).active_item_as::<Self>(cx)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if active_editor.entity_id() == cx.entity_id() {
|
||||
let edited_buffers_already_open = {
|
||||
let other_editors: Vec<Entity<Editor>> = workspace
|
||||
.read(cx)
|
||||
.panes()
|
||||
.iter()
|
||||
.flat_map(|pane| pane.read(cx).items_of_type::<Editor>())
|
||||
.filter(|editor| editor.entity_id() != cx.entity_id())
|
||||
.collect();
|
||||
|
||||
transaction.0.keys().all(|buffer| {
|
||||
other_editors.iter().any(|editor| {
|
||||
let multi_buffer = editor.read(cx).buffer();
|
||||
multi_buffer.read(cx).is_singleton()
|
||||
&& multi_buffer.read(cx).as_singleton().map_or(
|
||||
false,
|
||||
|singleton| {
|
||||
singleton.entity_id() == buffer.entity_id()
|
||||
},
|
||||
)
|
||||
})
|
||||
})
|
||||
};
|
||||
|
||||
if !edited_buffers_already_open {
|
||||
let workspace = workspace.downgrade();
|
||||
let transaction = transaction.clone();
|
||||
cx.defer_in(window, move |_, window, cx| {
|
||||
cx.spawn_in(window, async move |editor, cx| {
|
||||
Self::open_project_transaction(
|
||||
&editor,
|
||||
workspace,
|
||||
transaction,
|
||||
"Rename".to_string(),
|
||||
cx,
|
||||
)
|
||||
.await
|
||||
.ok()
|
||||
})
|
||||
.detach();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
},
|
||||
));
|
||||
|
@ -6282,7 +6336,7 @@ impl Editor {
|
|||
}
|
||||
|
||||
pub async fn open_project_transaction(
|
||||
this: &WeakEntity<Editor>,
|
||||
editor: &WeakEntity<Editor>,
|
||||
workspace: WeakEntity<Workspace>,
|
||||
transaction: ProjectTransaction,
|
||||
title: String,
|
||||
|
@ -6300,7 +6354,7 @@ impl Editor {
|
|||
|
||||
if let Some((buffer, transaction)) = entries.first() {
|
||||
if entries.len() == 1 {
|
||||
let excerpt = this.update(cx, |editor, cx| {
|
||||
let excerpt = editor.update(cx, |editor, cx| {
|
||||
editor
|
||||
.buffer()
|
||||
.read(cx)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue