Use Transaction instead of ProjectTransaction

Co-Authored-By: Antonio Scandurra <antonio@zed.dev>
This commit is contained in:
Kirill Bulatov 2023-05-25 15:49:07 +03:00
parent aa58d0fd77
commit e2ff829f98
6 changed files with 51 additions and 78 deletions

View file

@ -7444,18 +7444,11 @@ async fn test_on_input_format_from_host_to_guest(
let fake_language_server = fake_language_servers.next().await.unwrap(); let fake_language_server = fake_language_servers.next().await.unwrap();
cx_b.foreground().run_until_parked(); cx_b.foreground().run_until_parked();
// Type a on type formatting trigger character as the guest.
editor_a.update(cx_a, |editor, cx| {
editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
editor.handle_input(">", cx);
cx.focus(&editor_a);
});
// Receive an OnTypeFormatting request as the host's language server. // Receive an OnTypeFormatting request as the host's language server.
// Return some formattings from the host's language server. // Return some formattings from the host's language server.
cx_b.foreground().start_waiting(); fake_language_server.handle_request::<lsp::request::OnTypeFormatting, _, _>(
fake_language_server |params, _| async move {
.handle_request::<lsp::request::OnTypeFormatting, _, _>(|params, _| async move {
assert_eq!( assert_eq!(
params.text_document_position.text_document.uri, params.text_document_position.text_document.uri,
lsp::Url::from_file_path("/a/main.rs").unwrap(), lsp::Url::from_file_path("/a/main.rs").unwrap(),
@ -7469,18 +7462,27 @@ async fn test_on_input_format_from_host_to_guest(
new_text: "~<".to_string(), new_text: "~<".to_string(),
range: lsp::Range::new(lsp::Position::new(0, 14), lsp::Position::new(0, 14)), range: lsp::Range::new(lsp::Position::new(0, 14), lsp::Position::new(0, 14)),
}])) }]))
}) },
.next() );
.await // .next()
.unwrap(); // .await
cx_b.foreground().finish_waiting(); // .unwrap();
// Open the buffer on the guest and see that the formattings worked // Open the buffer on the guest and see that the formattings worked
let buffer_b = project_b let buffer_b = project_b
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx)) .update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx))
.await .await
.unwrap(); .unwrap();
// Type a on type formatting trigger character as the guest.
editor_a.update(cx_a, |editor, cx| {
cx.focus(&editor_a);
editor.change_selections(None, cx, |s| s.select_ranges([13..13]));
editor.handle_input(">", cx);
});
cx_b.foreground().run_until_parked(); cx_b.foreground().run_until_parked();
buffer_b.read_with(cx_b, |buffer, _| { buffer_b.read_with(cx_b, |buffer, _| {
assert_eq!(buffer.text(), "fn main() { a>~< }") assert_eq!(buffer.text(), "fn main() { a>~< }")
}); });

View file

@ -2518,8 +2518,6 @@ impl Editor {
return None; return None;
} }
let transaction_title = format!("OnTypeFormatting after {input}");
let workspace = self.workspace(cx)?;
let project = self.project.as_ref()?; let project = self.project.as_ref()?;
let position = self.selections.newest_anchor().head(); let position = self.selections.newest_anchor().head();
let (buffer, buffer_position) = self let (buffer, buffer_position) = self
@ -2527,20 +2525,11 @@ impl Editor {
.read(cx) .read(cx)
.text_anchor_for_position(position.clone(), cx)?; .text_anchor_for_position(position.clone(), cx)?;
let on_type_formatting = project.update(cx, |project, cx| { let on_type_formatting = project.update(cx, |project, cx| {
project.on_type_format(buffer, buffer_position, input, cx) project.on_type_format(buffer, buffer_position, input, true, cx)
}); });
Some(cx.spawn(|editor, mut cx| async move { Some(cx.spawn(|editor, mut cx| async move {
let project_transaction = on_type_formatting.await?; on_type_formatting.await?;
Self::open_project_transaction(
&editor,
workspace.downgrade(),
project_transaction,
transaction_title,
cx.clone(),
)
.await?;
editor.update(&mut cx, |editor, cx| { editor.update(&mut cx, |editor, cx| {
editor.refresh_document_highlights(cx); editor.refresh_document_highlights(cx);
})?; })?;

View file

@ -12,7 +12,7 @@ use language::{
point_from_lsp, point_to_lsp, point_from_lsp, point_to_lsp,
proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version}, proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version},
range_from_lsp, range_to_lsp, Anchor, Bias, Buffer, CachedLspAdapter, CharKind, CodeAction, range_from_lsp, range_to_lsp, Anchor, Bias, Buffer, CachedLspAdapter, CharKind, CodeAction,
Completion, OffsetRangeExt, PointUtf16, ToOffset, ToPointUtf16, Unclipped, Completion, OffsetRangeExt, PointUtf16, ToOffset, ToPointUtf16, Transaction, Unclipped,
}; };
use lsp::{DocumentHighlightKind, LanguageServer, LanguageServerId, ServerCapabilities}; use lsp::{DocumentHighlightKind, LanguageServer, LanguageServerId, ServerCapabilities};
use std::{cmp::Reverse, ops::Range, path::Path, sync::Arc}; use std::{cmp::Reverse, ops::Range, path::Path, sync::Arc};
@ -1628,7 +1628,7 @@ impl LspCommand for GetCodeActions {
#[async_trait(?Send)] #[async_trait(?Send)]
impl LspCommand for OnTypeFormatting { impl LspCommand for OnTypeFormatting {
type Response = ProjectTransaction; type Response = Option<Transaction>;
type LspRequest = lsp::request::OnTypeFormatting; type LspRequest = lsp::request::OnTypeFormatting;
type ProtoRequest = proto::OnTypeFormatting; type ProtoRequest = proto::OnTypeFormatting;
@ -1668,7 +1668,7 @@ impl LspCommand for OnTypeFormatting {
buffer: ModelHandle<Buffer>, buffer: ModelHandle<Buffer>,
server_id: LanguageServerId, server_id: LanguageServerId,
mut cx: AsyncAppContext, mut cx: AsyncAppContext,
) -> Result<ProjectTransaction> { ) -> Result<Option<Transaction>> {
if let Some(edits) = message { if let Some(edits) = message {
let (lsp_adapter, lsp_server) = let (lsp_adapter, lsp_server) =
language_server_for_buffer(&project, &buffer, server_id, &mut cx)?; language_server_for_buffer(&project, &buffer, server_id, &mut cx)?;
@ -1683,7 +1683,7 @@ impl LspCommand for OnTypeFormatting {
) )
.await .await
} else { } else {
Ok(ProjectTransaction::default()) Ok(None)
} }
} }
@ -1729,33 +1729,27 @@ impl LspCommand for OnTypeFormatting {
} }
fn response_to_proto( fn response_to_proto(
response: ProjectTransaction, response: Option<Transaction>,
project: &mut Project, _: &mut Project,
peer_id: PeerId, _: PeerId,
_: &clock::Global, _: &clock::Global,
cx: &mut AppContext, _: &mut AppContext,
) -> proto::OnTypeFormattingResponse { ) -> proto::OnTypeFormattingResponse {
let transaction = project.serialize_project_transaction_for_peer(response, peer_id, cx);
proto::OnTypeFormattingResponse { proto::OnTypeFormattingResponse {
transaction: Some(transaction), transaction: response
.map(|transaction| language::proto::serialize_transaction(&transaction)),
} }
} }
async fn response_from_proto( async fn response_from_proto(
self, self,
message: proto::OnTypeFormattingResponse, message: proto::OnTypeFormattingResponse,
project: ModelHandle<Project>, _: ModelHandle<Project>,
_: ModelHandle<Buffer>, _: ModelHandle<Buffer>,
mut cx: AsyncAppContext, _: AsyncAppContext,
) -> Result<ProjectTransaction> { ) -> Result<Option<Transaction>> {
let message = message let Some(transaction) = message.transaction else { return Ok(None) };
.transaction Ok(Some(language::proto::deserialize_transaction(transaction)?))
.ok_or_else(|| anyhow!("missing transaction"))?;
project
.update(&mut cx, |project, cx| {
project.deserialize_project_transaction(message, self.push_to_history, cx)
})
.await
} }
fn buffer_id_from_proto(message: &proto::OnTypeFormatting) -> u64 { fn buffer_id_from_proto(message: &proto::OnTypeFormatting) -> u64 {

View file

@ -4040,9 +4040,8 @@ impl Project {
buffer: ModelHandle<Buffer>, buffer: ModelHandle<Buffer>,
position: Anchor, position: Anchor,
trigger: String, trigger: String,
push_to_history: bool,
cx: &mut ModelContext<Self>, cx: &mut ModelContext<Self>,
) -> Task<Result<ProjectTransaction>> { ) -> Task<Result<Option<Transaction>>> {
if self.is_local() { if self.is_local() {
cx.spawn(|this, mut cx| async move { cx.spawn(|this, mut cx| async move {
// Do not allow multiple concurrent formatting requests for the // Do not allow multiple concurrent formatting requests for the
@ -4071,7 +4070,7 @@ impl Project {
.await?; .await?;
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
let position = position.to_point_utf16(buffer.read(cx)); let position = position.to_point_utf16(buffer.read(cx));
this.on_type_format(buffer, position, trigger, cx) this.on_type_format(buffer, position, trigger, false, cx)
}) })
.await .await
}) })
@ -4084,16 +4083,13 @@ impl Project {
trigger, trigger,
version: serialize_version(&buffer.read(cx).version()), version: serialize_version(&buffer.read(cx).version()),
}; };
cx.spawn(|this, mut cx| async move { cx.spawn(|_, _| async move {
let response = client client
.request(request) .request(request)
.await? .await?
.transaction .transaction
.ok_or_else(|| anyhow!("missing transaction"))?; .map(language::proto::deserialize_transaction)
this.update(&mut cx, |this, cx| { .transpose()
this.deserialize_project_transaction(response, push_to_history, cx)
})
.await
}) })
} else { } else {
Task::ready(Err(anyhow!("project does not have a remote id"))) Task::ready(Err(anyhow!("project does not have a remote id")))
@ -4108,7 +4104,7 @@ impl Project {
_: Arc<CachedLspAdapter>, _: Arc<CachedLspAdapter>,
language_server: Arc<LanguageServer>, language_server: Arc<LanguageServer>,
cx: &mut AsyncAppContext, cx: &mut AsyncAppContext,
) -> Result<ProjectTransaction> { ) -> Result<Option<Transaction>> {
let edits = this let edits = this
.update(cx, |this, cx| { .update(cx, |this, cx| {
this.edits_from_lsp( this.edits_from_lsp(
@ -4139,12 +4135,7 @@ impl Project {
} }
}); });
let mut project_transaction = ProjectTransaction::default(); Ok(transaction)
if let Some(transaction) = transaction {
project_transaction.0.insert(buffer_to_edit, transaction);
}
Ok(project_transaction)
} }
async fn deserialize_workspace_edit( async fn deserialize_workspace_edit(
@ -4317,8 +4308,9 @@ impl Project {
buffer: ModelHandle<Buffer>, buffer: ModelHandle<Buffer>,
position: T, position: T,
trigger: String, trigger: String,
push_to_history: bool,
cx: &mut ModelContext<Self>, cx: &mut ModelContext<Self>,
) -> Task<Result<ProjectTransaction>> { ) -> Task<Result<Option<Transaction>>> {
let tab_size = buffer.read_with(cx, |buffer, cx| { let tab_size = buffer.read_with(cx, |buffer, cx| {
let language_name = buffer.language().map(|language| language.name()); let language_name = buffer.language().map(|language| language.name());
language_settings(language_name.as_deref(), cx).tab_size language_settings(language_name.as_deref(), cx).tab_size
@ -4330,7 +4322,7 @@ impl Project {
position, position,
trigger, trigger,
options: lsp_command::lsp_formatting_options(tab_size.get()).into(), options: lsp_command::lsp_formatting_options(tab_size.get()).into(),
push_to_history: true, push_to_history,
}, },
cx, cx,
) )
@ -5912,7 +5904,6 @@ impl Project {
_: Arc<Client>, _: Arc<Client>,
mut cx: AsyncAppContext, mut cx: AsyncAppContext,
) -> Result<proto::OnTypeFormattingResponse> { ) -> Result<proto::OnTypeFormattingResponse> {
let sender_id = envelope.original_sender_id()?;
let on_type_formatting = this.update(&mut cx, |this, cx| { let on_type_formatting = this.update(&mut cx, |this, cx| {
let buffer = this let buffer = this
.opened_buffers .opened_buffers
@ -5928,18 +5919,15 @@ impl Project {
buffer, buffer,
position, position,
envelope.payload.trigger.clone(), envelope.payload.trigger.clone(),
false,
cx, cx,
)) ))
})?; })?;
let project_transaction = on_type_formatting.await?; let transaction = on_type_formatting
let project_transaction = this.update(&mut cx, |this, cx| { .await?
this.serialize_project_transaction_for_peer(project_transaction, sender_id, cx) .as_ref()
}); .map(language::proto::serialize_transaction);
Ok(proto::OnTypeFormattingResponse { Ok(proto::OnTypeFormattingResponse { transaction })
transaction: Some(project_transaction),
})
} }
async fn handle_lsp_command<T: LspCommand>( async fn handle_lsp_command<T: LspCommand>(

View file

@ -682,7 +682,7 @@ message OnTypeFormatting {
} }
message OnTypeFormattingResponse { message OnTypeFormattingResponse {
ProjectTransaction transaction = 1; Transaction transaction = 1;
} }
message PerformRenameResponse { message PerformRenameResponse {

View file

@ -6,4 +6,4 @@ pub use conn::Connection;
pub use peer::*; pub use peer::*;
mod macros; mod macros;
pub const PROTOCOL_VERSION: u32 = 55; pub const PROTOCOL_VERSION: u32 = 56;