Apply code actions remotely
This commit is contained in:
parent
aedf31e2d8
commit
dca974c7d4
9 changed files with 409 additions and 86 deletions
|
@ -216,6 +216,13 @@ pub trait File {
|
|||
cx: &mut MutableAppContext,
|
||||
) -> Task<Result<Vec<clock::Local>>>;
|
||||
|
||||
fn code_actions(
|
||||
&self,
|
||||
buffer_id: u64,
|
||||
position: Anchor,
|
||||
cx: &mut MutableAppContext,
|
||||
) -> Task<Result<Vec<CodeAction<Anchor>>>>;
|
||||
|
||||
fn buffer_updated(&self, buffer_id: u64, operation: Operation, cx: &mut MutableAppContext);
|
||||
|
||||
fn buffer_removed(&self, buffer_id: u64, cx: &mut MutableAppContext);
|
||||
|
@ -304,6 +311,15 @@ impl File for FakeFile {
|
|||
Task::ready(Ok(Default::default()))
|
||||
}
|
||||
|
||||
fn code_actions(
|
||||
&self,
|
||||
_: u64,
|
||||
_: Anchor,
|
||||
_: &mut MutableAppContext,
|
||||
) -> Task<Result<Vec<CodeAction<Anchor>>>> {
|
||||
Task::ready(Ok(Default::default()))
|
||||
}
|
||||
|
||||
fn buffer_updated(&self, _: u64, _: Operation, _: &mut MutableAppContext) {}
|
||||
|
||||
fn buffer_removed(&self, _: u64, _: &mut MutableAppContext) {}
|
||||
|
@ -1350,10 +1366,29 @@ impl Buffer {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn push_transaction(
|
||||
&mut self,
|
||||
edit_ids: impl IntoIterator<Item = clock::Local>,
|
||||
now: Instant,
|
||||
) {
|
||||
self.text.push_transaction(edit_ids, now);
|
||||
}
|
||||
|
||||
pub fn avoid_grouping_next_transaction(&mut self) {
|
||||
self.text.avoid_grouping_next_transaction();
|
||||
}
|
||||
|
||||
pub fn forget_transaction(&mut self, transaction_id: TransactionId) {
|
||||
self.text.forget_transaction(transaction_id);
|
||||
}
|
||||
|
||||
pub fn wait_for_edits(
|
||||
&mut self,
|
||||
edit_ids: impl IntoIterator<Item = clock::Local>,
|
||||
) -> impl Future<Output = ()> {
|
||||
self.text.wait_for_edits(edit_ids)
|
||||
}
|
||||
|
||||
pub fn set_active_selections(
|
||||
&mut self,
|
||||
selections: Arc<[Selection<Anchor>]>,
|
||||
|
@ -1873,6 +1908,8 @@ impl Buffer {
|
|||
} else {
|
||||
return Task::ready(Ok(Default::default()));
|
||||
};
|
||||
let position = position.to_point_utf16(self);
|
||||
let anchor = self.anchor_after(position);
|
||||
|
||||
if let Some(file) = file.as_local() {
|
||||
let server = if let Some(language_server) = self.language_server.as_ref() {
|
||||
|
@ -1881,8 +1918,6 @@ impl Buffer {
|
|||
return Task::ready(Ok(Default::default()));
|
||||
};
|
||||
let abs_path = file.abs_path(cx);
|
||||
let position = position.to_point_utf16(self);
|
||||
let anchor = self.anchor_after(position);
|
||||
|
||||
cx.foreground().spawn(async move {
|
||||
let actions = server
|
||||
|
@ -1922,8 +1957,7 @@ impl Buffer {
|
|||
Ok(actions)
|
||||
})
|
||||
} else {
|
||||
log::info!("code actions are not implemented for guests");
|
||||
Task::ready(Ok(Default::default()))
|
||||
file.code_actions(self.remote_id(), anchor, cx.as_mut())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1959,7 +1993,7 @@ impl Buffer {
|
|||
let edits = this.apply_lsp_edits(additional_edits, None, cx);
|
||||
if let Some(transaction_id) = this.end_transaction(cx) {
|
||||
if !push_to_history {
|
||||
this.text.forget_transaction(transaction_id);
|
||||
this.forget_transaction(transaction_id);
|
||||
}
|
||||
}
|
||||
Ok(edits?.into_iter().map(|(_, edit_id)| edit_id).collect())
|
||||
|
@ -1976,12 +2010,13 @@ impl Buffer {
|
|||
);
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let edit_ids = apply_edits.await?;
|
||||
this.update(&mut cx, |this, _| this.text.wait_for_edits(&edit_ids))
|
||||
.await;
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.wait_for_edits(edit_ids.iter().copied())
|
||||
})
|
||||
.await;
|
||||
if push_to_history {
|
||||
this.update(&mut cx, |this, _| {
|
||||
this.text
|
||||
.push_transaction(edit_ids.iter().copied(), Instant::now());
|
||||
this.push_transaction(edit_ids.iter().copied(), Instant::now());
|
||||
});
|
||||
}
|
||||
Ok(edit_ids)
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
use crate::{
|
||||
diagnostic_set::DiagnosticEntry, Completion, CompletionLabel, Diagnostic, Language, Operation,
|
||||
diagnostic_set::DiagnosticEntry, CodeAction, Completion, CompletionLabel, Diagnostic, Language,
|
||||
Operation,
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use clock::ReplicaId;
|
||||
use collections::HashSet;
|
||||
use lsp::DiagnosticSeverity;
|
||||
use rpc::proto;
|
||||
use std::sync::Arc;
|
||||
use std::{ops::Range, sync::Arc};
|
||||
use text::*;
|
||||
|
||||
pub use proto::{Buffer, BufferState, SelectionSet};
|
||||
|
@ -411,3 +412,62 @@ pub fn deserialize_completion(
|
|||
lsp_completion,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn serialize_code_action(action: &CodeAction<Anchor>) -> proto::CodeAction {
|
||||
proto::CodeAction {
|
||||
position: Some(serialize_anchor(&action.position)),
|
||||
lsp_action: serde_json::to_vec(&action.lsp_action).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deserialize_code_action(action: proto::CodeAction) -> Result<CodeAction<Anchor>> {
|
||||
let position = action
|
||||
.position
|
||||
.and_then(deserialize_anchor)
|
||||
.ok_or_else(|| anyhow!("invalid position"))?;
|
||||
let lsp_action = serde_json::from_slice(&action.lsp_action)?;
|
||||
Ok(CodeAction {
|
||||
position,
|
||||
lsp_action,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn serialize_code_action_edit(
|
||||
edit_id: clock::Local,
|
||||
old_range: &Range<Anchor>,
|
||||
) -> proto::CodeActionEdit {
|
||||
proto::CodeActionEdit {
|
||||
id: Some(serialize_edit_id(edit_id)),
|
||||
old_start: Some(serialize_anchor(&old_range.start)),
|
||||
old_end: Some(serialize_anchor(&old_range.end)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deserialize_code_action_edit(
|
||||
edit: proto::CodeActionEdit,
|
||||
) -> Result<(Range<Anchor>, clock::Local)> {
|
||||
let old_start = edit
|
||||
.old_start
|
||||
.and_then(deserialize_anchor)
|
||||
.ok_or_else(|| anyhow!("invalid old_start"))?;
|
||||
let old_end = edit
|
||||
.old_end
|
||||
.and_then(deserialize_anchor)
|
||||
.ok_or_else(|| anyhow!("invalid old_end"))?;
|
||||
let edit_id = deserialize_edit_id(edit.id.ok_or_else(|| anyhow!("invalid edit_id"))?);
|
||||
Ok((old_start..old_end, edit_id))
|
||||
}
|
||||
|
||||
pub fn serialize_edit_id(edit_id: clock::Local) -> proto::EditId {
|
||||
proto::EditId {
|
||||
replica_id: edit_id.replica_id as u32,
|
||||
local_timestamp: edit_id.value,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deserialize_edit_id(edit_id: proto::EditId) -> clock::Local {
|
||||
clock::Local {
|
||||
replica_id: edit_id.replica_id as ReplicaId,
|
||||
value: edit_id.local_timestamp,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue