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);
|
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(
|
pub async fn open_project_transaction(
|
||||||
this: &WeakEntity<Editor>,
|
editor: &WeakEntity<Editor>,
|
||||||
workspace: WeakEntity<Workspace>,
|
workspace: WeakEntity<Workspace>,
|
||||||
transaction: ProjectTransaction,
|
transaction: ProjectTransaction,
|
||||||
title: String,
|
title: String,
|
||||||
|
@ -6300,7 +6354,7 @@ impl Editor {
|
||||||
|
|
||||||
if let Some((buffer, transaction)) = entries.first() {
|
if let Some((buffer, transaction)) = entries.first() {
|
||||||
if entries.len() == 1 {
|
if entries.len() == 1 {
|
||||||
let excerpt = this.update(cx, |editor, cx| {
|
let excerpt = editor.update(cx, |editor, cx| {
|
||||||
editor
|
editor
|
||||||
.buffer()
|
.buffer()
|
||||||
.read(cx)
|
.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>);
|
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 EventEmitter<BufferStoreEvent> for BufferStore {}
|
||||||
|
|
||||||
impl RemoteBufferStore {
|
impl RemoteBufferStore {
|
||||||
|
|
|
@ -8762,7 +8762,7 @@ impl LspStore {
|
||||||
(root_path.join(&old_path), root_path.join(&new_path))
|
(root_path.join(&old_path), root_path.join(&new_path))
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::will_rename_entry(
|
let _transaction = Self::will_rename_entry(
|
||||||
this.downgrade(),
|
this.downgrade(),
|
||||||
worktree_id,
|
worktree_id,
|
||||||
&old_abs_path,
|
&old_abs_path,
|
||||||
|
@ -9224,7 +9224,7 @@ impl LspStore {
|
||||||
new_path: &Path,
|
new_path: &Path,
|
||||||
is_dir: bool,
|
is_dir: bool,
|
||||||
cx: AsyncApp,
|
cx: AsyncApp,
|
||||||
) -> Task<()> {
|
) -> Task<ProjectTransaction> {
|
||||||
let old_uri = lsp::Url::from_file_path(old_path).ok().map(String::from);
|
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);
|
let new_uri = lsp::Url::from_file_path(new_path).ok().map(String::from);
|
||||||
cx.spawn(async move |cx| {
|
cx.spawn(async move |cx| {
|
||||||
|
@ -9257,7 +9257,7 @@ impl LspStore {
|
||||||
.log_err()
|
.log_err()
|
||||||
.flatten()?;
|
.flatten()?;
|
||||||
|
|
||||||
LocalLspStore::deserialize_workspace_edit(
|
let transaction = LocalLspStore::deserialize_workspace_edit(
|
||||||
this.upgrade()?,
|
this.upgrade()?,
|
||||||
edit,
|
edit,
|
||||||
false,
|
false,
|
||||||
|
@ -9265,8 +9265,8 @@ impl LspStore {
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.ok();
|
.ok()?;
|
||||||
Some(())
|
Some(transaction)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
tasks.push(apply_edit);
|
tasks.push(apply_edit);
|
||||||
|
@ -9276,11 +9276,17 @@ impl LspStore {
|
||||||
})
|
})
|
||||||
.ok()
|
.ok()
|
||||||
.flatten();
|
.flatten();
|
||||||
|
let mut merged_transaction = ProjectTransaction::default();
|
||||||
for task in tasks {
|
for task in tasks {
|
||||||
// Await on tasks sequentially so that the order of application of edits is deterministic
|
// 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)
|
// (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),
|
RevealInProjectPanel(ProjectEntryId),
|
||||||
SnippetEdit(BufferId, Vec<(lsp::Range, Snippet)>),
|
SnippetEdit(BufferId, Vec<(lsp::Range, Snippet)>),
|
||||||
ExpandedAllForEntry(WorktreeId, ProjectEntryId),
|
ExpandedAllForEntry(WorktreeId, ProjectEntryId),
|
||||||
|
EntryRenamed(ProjectTransaction),
|
||||||
AgentLocationChanged,
|
AgentLocationChanged,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2119,7 +2120,7 @@ impl Project {
|
||||||
let is_root_entry = self.entry_is_worktree_root(entry_id, cx);
|
let is_root_entry = self.entry_is_worktree_root(entry_id, cx);
|
||||||
|
|
||||||
let lsp_store = self.lsp_store().downgrade();
|
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 (old_abs_path, new_abs_path) = {
|
||||||
let root_path = worktree.read_with(cx, |this, _| this.abs_path())?;
|
let root_path = worktree.read_with(cx, |this, _| this.abs_path())?;
|
||||||
let new_abs_path = if is_root_entry {
|
let new_abs_path = if is_root_entry {
|
||||||
|
@ -2129,7 +2130,7 @@ impl Project {
|
||||||
};
|
};
|
||||||
(root_path.join(&old_path), new_abs_path)
|
(root_path.join(&old_path), new_abs_path)
|
||||||
};
|
};
|
||||||
LspStore::will_rename_entry(
|
let transaction = LspStore::will_rename_entry(
|
||||||
lsp_store.clone(),
|
lsp_store.clone(),
|
||||||
worktree_id,
|
worktree_id,
|
||||||
&old_abs_path,
|
&old_abs_path,
|
||||||
|
@ -2145,6 +2146,12 @@ impl Project {
|
||||||
})?
|
})?
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
project
|
||||||
|
.update(cx, |_, cx| {
|
||||||
|
cx.emit(Event::EntryRenamed(transaction));
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
|
||||||
lsp_store
|
lsp_store
|
||||||
.read_with(cx, |this, _| {
|
.read_with(cx, |this, _| {
|
||||||
this.did_rename_entry(worktree_id, &old_abs_path, &new_abs_path, is_dir);
|
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