Allow opening of buffers associated with a project symbol

This commit is contained in:
Antonio Scandurra 2022-02-22 16:26:01 +01:00
parent 2a6d486d14
commit f0195ac3a3
8 changed files with 237 additions and 121 deletions

2
Cargo.lock generated
View file

@ -3563,9 +3563,11 @@ dependencies = [
name = "project_symbols" name = "project_symbols"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow",
"editor", "editor",
"fuzzy", "fuzzy",
"gpui", "gpui",
"language",
"ordered-float", "ordered-float",
"postage", "postage",
"project", "project",

View file

@ -342,7 +342,7 @@ impl LspCommand for GetDefinition {
for (target_uri, target_range) in unresolved_locations { for (target_uri, target_range) in unresolved_locations {
let target_buffer_handle = project let target_buffer_handle = project
.update(&mut cx, |this, cx| { .update(&mut cx, |this, cx| {
this.open_local_buffer_from_lsp_path( this.open_local_buffer_via_lsp(
target_uri, target_uri,
language.name().to_string(), language.name().to_string(),
language_server.clone(), language_server.clone(),

View file

@ -118,8 +118,10 @@ pub struct Definition {
pub target_range: Range<language::Anchor>, pub target_range: Range<language::Anchor>,
} }
#[derive(Debug)] #[derive(Clone, Debug)]
pub struct Symbol { pub struct Symbol {
pub worktree_id: WorktreeId,
pub language_name: String,
pub label: CodeLabel, pub label: CodeLabel,
pub lsp_symbol: lsp::SymbolInformation, pub lsp_symbol: lsp::SymbolInformation,
} }
@ -193,6 +195,7 @@ impl Project {
client.add_entity_request_handler(Self::handle_lsp_command::<PrepareRename>); client.add_entity_request_handler(Self::handle_lsp_command::<PrepareRename>);
client.add_entity_request_handler(Self::handle_lsp_command::<PerformRename>); client.add_entity_request_handler(Self::handle_lsp_command::<PerformRename>);
client.add_entity_request_handler(Self::handle_get_project_symbols); client.add_entity_request_handler(Self::handle_get_project_symbols);
client.add_entity_request_handler(Self::handle_open_buffer_for_symbol);
client.add_entity_request_handler(Self::handle_open_buffer); client.add_entity_request_handler(Self::handle_open_buffer);
client.add_entity_request_handler(Self::handle_save_buffer); client.add_entity_request_handler(Self::handle_save_buffer);
} }
@ -653,7 +656,7 @@ impl Project {
}) })
} }
fn open_local_buffer_from_lsp_path( fn open_local_buffer_via_lsp(
&mut self, &mut self,
abs_path: lsp::Url, abs_path: lsp::Url,
lang_name: String, lang_name: String,
@ -1223,22 +1226,18 @@ impl Project {
self.request_lsp(buffer.clone(), GetDefinition { position }, cx) self.request_lsp(buffer.clone(), GetDefinition { position }, cx)
} }
pub fn symbols( pub fn symbols(&self, query: &str, cx: &mut ModelContext<Self>) -> Task<Result<Vec<Symbol>>> {
&self,
query: &str,
cx: &mut ModelContext<Self>,
) -> Task<Result<HashMap<String, Vec<Symbol>>>> {
if self.is_local() { if self.is_local() {
let mut language_servers = HashMap::default(); let mut language_servers = HashMap::default();
for ((_, language_name), language_server) in self.language_servers.iter() { for ((worktree_id, language_name), language_server) in self.language_servers.iter() {
let language = self.languages.get_language(language_name).unwrap(); let language = self.languages.get_language(language_name).unwrap();
language_servers language_servers
.entry(Arc::as_ptr(language_server)) .entry(Arc::as_ptr(language_server))
.or_insert((language_server.clone(), language.clone())); .or_insert((language_server.clone(), *worktree_id, language.clone()));
} }
let mut requests = Vec::new(); let mut requests = Vec::new();
for (language_server, _) in language_servers.values() { for (language_server, _, _) in language_servers.values() {
requests.push(language_server.request::<lsp::request::WorkspaceSymbol>( requests.push(language_server.request::<lsp::request::WorkspaceSymbol>(
lsp::WorkspaceSymbolParams { lsp::WorkspaceSymbolParams {
query: query.to_string(), query: query.to_string(),
@ -1249,17 +1248,21 @@ impl Project {
cx.foreground().spawn(async move { cx.foreground().spawn(async move {
let responses = futures::future::try_join_all(requests).await?; let responses = futures::future::try_join_all(requests).await?;
let mut symbols = HashMap::default(); let mut symbols = Vec::new();
for ((_, language), lsp_symbols) in language_servers.into_values().zip(responses) { for ((_, worktree_id, language), lsp_symbols) in
let language_symbols = symbols language_servers.into_values().zip(responses)
.entry(language.name().to_string()) {
.or_insert(Vec::new()); symbols.extend(lsp_symbols.into_iter().flatten().map(|lsp_symbol| {
for lsp_symbol in lsp_symbols.into_iter().flatten() {
let label = language let label = language
.label_for_symbol(&lsp_symbol) .label_for_symbol(&lsp_symbol)
.unwrap_or_else(|| CodeLabel::plain(lsp_symbol.name.clone(), None)); .unwrap_or_else(|| CodeLabel::plain(lsp_symbol.name.clone(), None));
language_symbols.push(Symbol { label, lsp_symbol }); Symbol {
} worktree_id,
language_name: language.name().to_string(),
label,
lsp_symbol,
}
}));
} }
Ok(symbols) Ok(symbols)
}) })
@ -1270,40 +1273,15 @@ impl Project {
}); });
cx.spawn_weak(|this, cx| async move { cx.spawn_weak(|this, cx| async move {
let response = request.await?; let response = request.await?;
let mut symbols = HashMap::default(); let mut symbols = Vec::new();
if let Some(this) = this.upgrade(&cx) { if let Some(this) = this.upgrade(&cx) {
this.read_with(&cx, |this, _| { this.read_with(&cx, |this, _| {
let mut serialized_symbols = response.symbols.into_iter(); symbols.extend(
for (language_name, symbol_count) in response response
.languages .symbols
.into_iter() .into_iter()
.zip(response.symbol_counts_per_language) .filter_map(|symbol| this.deserialize_symbol(symbol).log_err()),
{ );
let language = this.languages.get_language(&language_name);
let language_symbols =
symbols.entry(language_name).or_insert(Vec::new());
language_symbols.extend(
serialized_symbols
.by_ref()
.take(symbol_count as usize)
.filter_map(|serialized_symbol| {
let lsp_symbol =
serde_json::from_slice(&serialized_symbol.lsp_symbol)
.log_err()?;
Some(Symbol {
label: language
.and_then(|language| {
language.label_for_symbol(&lsp_symbol)
})
.unwrap_or(CodeLabel::plain(
lsp_symbol.name.clone(),
None,
)),
lsp_symbol,
})
}),
);
}
}) })
} }
Ok(symbols) Ok(symbols)
@ -1313,6 +1291,45 @@ impl Project {
} }
} }
pub fn open_buffer_for_symbol(
&mut self,
symbol: &Symbol,
cx: &mut ModelContext<Self>,
) -> Task<Result<ModelHandle<Buffer>>> {
if self.is_local() {
let language_server = if let Some(server) = self
.language_servers
.get(&(symbol.worktree_id, symbol.language_name.clone()))
{
server.clone()
} else {
return Task::ready(Err(anyhow!(
"language server for worktree and language not found"
)));
};
self.open_local_buffer_via_lsp(
symbol.lsp_symbol.location.uri.clone(),
symbol.language_name.clone(),
language_server,
cx,
)
} else if let Some(project_id) = self.remote_id() {
let request = self.client.request(proto::OpenBufferForSymbol {
project_id,
symbol: Some(serialize_symbol(symbol)),
});
cx.spawn(|this, mut cx| async move {
let response = request.await?;
let buffer = response.buffer.ok_or_else(|| anyhow!("invalid buffer"))?;
this.update(&mut cx, |this, cx| this.deserialize_buffer(buffer, cx))
.await
})
} else {
Task::ready(Err(anyhow!("project does not have a remote id")))
}
}
pub fn completions<T: ToPointUtf16>( pub fn completions<T: ToPointUtf16>(
&self, &self,
source_buffer_handle: &ModelHandle<Buffer>, source_buffer_handle: &ModelHandle<Buffer>,
@ -1785,7 +1802,7 @@ impl Project {
lsp::DocumentChangeOperation::Edit(op) => { lsp::DocumentChangeOperation::Edit(op) => {
let buffer_to_edit = this let buffer_to_edit = this
.update(cx, |this, cx| { .update(cx, |this, cx| {
this.open_local_buffer_from_lsp_path( this.open_local_buffer_via_lsp(
op.text_document.uri, op.text_document.uri,
language_name.clone(), language_name.clone(),
language_server.clone(), language_server.clone(),
@ -2634,21 +2651,31 @@ impl Project {
}) })
.await?; .await?;
let mut languages = Vec::new();
let mut symbol_counts_per_language = Vec::new();
let mut serialized_symbols = Vec::new();
for (language_name, language_symbols) in symbols {
languages.push(language_name);
symbol_counts_per_language.push(language_symbols.len() as u64);
serialized_symbols.extend(language_symbols.into_iter().map(|symbol| proto::Symbol {
lsp_symbol: serde_json::to_vec(&symbol.lsp_symbol).unwrap(),
}));
}
Ok(proto::GetProjectSymbolsResponse { Ok(proto::GetProjectSymbolsResponse {
languages, symbols: symbols.iter().map(serialize_symbol).collect(),
symbol_counts_per_language, })
symbols: serialized_symbols, }
async fn handle_open_buffer_for_symbol(
this: ModelHandle<Self>,
envelope: TypedEnvelope<proto::OpenBufferForSymbol>,
_: Arc<Client>,
mut cx: AsyncAppContext,
) -> Result<proto::OpenBufferForSymbolResponse> {
let peer_id = envelope.original_sender_id()?;
let symbol = envelope
.payload
.symbol
.ok_or_else(|| anyhow!("invalid symbol"))?;
let symbol = this.read_with(&cx, |this, _| this.deserialize_symbol(symbol))?;
let buffer = this
.update(&mut cx, |this, cx| this.open_buffer_for_symbol(&symbol, cx))
.await?;
Ok(proto::OpenBufferForSymbolResponse {
buffer: Some(this.update(&mut cx, |this, cx| {
this.serialize_buffer_for_peer(&buffer, peer_id, cx)
})),
}) })
} }
@ -2813,6 +2840,21 @@ impl Project {
}) })
} }
fn deserialize_symbol(&self, serialized_symbol: proto::Symbol) -> Result<Symbol> {
let language = self
.languages
.get_language(&serialized_symbol.language_name);
let lsp_symbol = serde_json::from_slice(&serialized_symbol.lsp_symbol)?;
Ok(Symbol {
worktree_id: WorktreeId::from_proto(serialized_symbol.worktree_id),
language_name: serialized_symbol.language_name.clone(),
label: language
.and_then(|language| language.label_for_symbol(&lsp_symbol))
.unwrap_or(CodeLabel::plain(lsp_symbol.name.clone(), None)),
lsp_symbol,
})
}
async fn handle_close_buffer( async fn handle_close_buffer(
this: ModelHandle<Self>, this: ModelHandle<Self>,
envelope: TypedEnvelope<proto::CloseBuffer>, envelope: TypedEnvelope<proto::CloseBuffer>,
@ -3094,6 +3136,14 @@ impl From<lsp::DeleteFileOptions> for fs::RemoveOptions {
} }
} }
fn serialize_symbol(symbol: &Symbol) -> proto::Symbol {
proto::Symbol {
worktree_id: symbol.worktree_id.to_proto(),
language_name: symbol.language_name.clone(),
lsp_symbol: serde_json::to_vec(&symbol.lsp_symbol).unwrap(),
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{Event, *}; use super::{Event, *};

View file

@ -10,10 +10,12 @@ path = "src/project_symbols.rs"
editor = { path = "../editor" } editor = { path = "../editor" }
fuzzy = { path = "../fuzzy" } fuzzy = { path = "../fuzzy" }
gpui = { path = "../gpui" } gpui = { path = "../gpui" }
language = { path = "../language" }
project = { path = "../project" } project = { path = "../project" }
text = { path = "../text" } text = { path = "../text" }
workspace = { path = "../workspace" } workspace = { path = "../workspace" }
util = { path = "../util" } util = { path = "../util" }
anyhow = "1.0.38"
ordered-float = "2.1.1" ordered-float = "2.1.1"
postage = { version = "0.4", features = ["futures-traits"] } postage = { version = "0.4", features = ["futures-traits"] }
smol = "1.2" smol = "1.2"

View file

@ -1,5 +1,6 @@
use editor::{ use editor::{
combine_syntax_and_fuzzy_match_highlights, styled_runs_for_code_label, Editor, EditorSettings, combine_syntax_and_fuzzy_match_highlights, items::BufferItemHandle, styled_runs_for_code_label,
Autoscroll, Bias, Editor, EditorSettings,
}; };
use fuzzy::{StringMatch, StringMatchCandidate}; use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{ use gpui::{
@ -9,6 +10,7 @@ use gpui::{
AppContext, Axis, Entity, ModelHandle, MutableAppContext, RenderContext, Task, View, AppContext, Axis, Entity, ModelHandle, MutableAppContext, RenderContext, Task, View,
ViewContext, ViewHandle, WeakViewHandle, ViewContext, ViewHandle, WeakViewHandle,
}; };
use language::range_from_lsp;
use ordered_float::OrderedFloat; use ordered_float::OrderedFloat;
use postage::watch; use postage::watch;
use project::{Project, Symbol}; use project::{Project, Symbol};
@ -52,6 +54,7 @@ pub struct ProjectSymbolsView {
pub enum Event { pub enum Event {
Dismissed, Dismissed,
Selected(Symbol),
} }
impl Entity for ProjectSymbolsView { impl Entity for ProjectSymbolsView {
@ -170,7 +173,13 @@ impl ProjectSymbolsView {
} }
fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) { fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
cx.emit(Event::Dismissed); if let Some(symbol) = self
.matches
.get(self.selected_match_index)
.map(|mat| self.symbols[mat.candidate_id].clone())
{
cx.emit(Event::Selected(symbol));
}
} }
fn update_matches(&mut self, cx: &mut ViewContext<Self>) { fn update_matches(&mut self, cx: &mut ViewContext<Self>) {
@ -180,12 +189,7 @@ impl ProjectSymbolsView {
.project .project
.update(cx, |project, cx| project.symbols(&query, cx)); .update(cx, |project, cx| project.symbols(&query, cx));
self.pending_symbols_task = cx.spawn_weak(|this, mut cx| async move { self.pending_symbols_task = cx.spawn_weak(|this, mut cx| async move {
let symbols = symbols let symbols = symbols.await.log_err()?;
.await
.log_err()?
.into_values()
.flatten()
.collect::<Vec<_>>();
if let Some(this) = this.upgrade(&cx) { if let Some(this) = this.upgrade(&cx) {
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
this.match_candidates = symbols this.match_candidates = symbols
@ -336,6 +340,34 @@ impl ProjectSymbolsView {
) { ) {
match event { match event {
Event::Dismissed => workspace.dismiss_modal(cx), Event::Dismissed => workspace.dismiss_modal(cx),
Event::Selected(symbol) => {
let buffer = workspace
.project()
.update(cx, |project, cx| project.open_buffer_for_symbol(symbol, cx));
let symbol = symbol.clone();
cx.spawn(|workspace, mut cx| async move {
let buffer = buffer.await?;
let range = range_from_lsp(symbol.lsp_symbol.location.range);
workspace.update(&mut cx, |workspace, cx| {
let start;
let end;
{
let buffer = buffer.read(cx);
start = buffer.clip_point_utf16(range.start, Bias::Left);
end = buffer.clip_point_utf16(range.end, Bias::Left);
}
let editor = workspace.open_item(BufferItemHandle(buffer), cx);
let editor = editor.downcast::<Editor>().unwrap();
editor.update(cx, |editor, cx| {
editor.select_ranges([start..end], Some(Autoscroll::Center), cx);
});
});
Ok::<_, anyhow::Error>(())
})
.detach_and_log_err(cx);
workspace.dismiss_modal(cx);
}
} }
} }
} }

View file

@ -25,53 +25,55 @@ message Envelope {
GetDefinitionResponse get_definition_response = 19; GetDefinitionResponse get_definition_response = 19;
GetProjectSymbols get_project_symbols = 20; GetProjectSymbols get_project_symbols = 20;
GetProjectSymbolsResponse get_project_symbols_response = 21; GetProjectSymbolsResponse get_project_symbols_response = 21;
OpenBufferForSymbol open_buffer_for_symbol = 22;
OpenBufferForSymbolResponse open_buffer_for_symbol_response = 23;
RegisterWorktree register_worktree = 22; RegisterWorktree register_worktree = 24;
UnregisterWorktree unregister_worktree = 23; UnregisterWorktree unregister_worktree = 25;
ShareWorktree share_worktree = 24; ShareWorktree share_worktree = 26;
UpdateWorktree update_worktree = 25; UpdateWorktree update_worktree = 27;
UpdateDiagnosticSummary update_diagnostic_summary = 26; UpdateDiagnosticSummary update_diagnostic_summary = 28;
DiskBasedDiagnosticsUpdating disk_based_diagnostics_updating = 27; DiskBasedDiagnosticsUpdating disk_based_diagnostics_updating = 29;
DiskBasedDiagnosticsUpdated disk_based_diagnostics_updated = 28; DiskBasedDiagnosticsUpdated disk_based_diagnostics_updated = 30;
OpenBuffer open_buffer = 29; OpenBuffer open_buffer = 31;
OpenBufferResponse open_buffer_response = 30; OpenBufferResponse open_buffer_response = 32;
CloseBuffer close_buffer = 31; CloseBuffer close_buffer = 33;
UpdateBuffer update_buffer = 32; UpdateBuffer update_buffer = 34;
UpdateBufferFile update_buffer_file = 33; UpdateBufferFile update_buffer_file = 35;
SaveBuffer save_buffer = 34; SaveBuffer save_buffer = 36;
BufferSaved buffer_saved = 35; BufferSaved buffer_saved = 37;
BufferReloaded buffer_reloaded = 36; BufferReloaded buffer_reloaded = 38;
FormatBuffers format_buffers = 37; FormatBuffers format_buffers = 39;
FormatBuffersResponse format_buffers_response = 38; FormatBuffersResponse format_buffers_response = 40;
GetCompletions get_completions = 39; GetCompletions get_completions = 41;
GetCompletionsResponse get_completions_response = 40; GetCompletionsResponse get_completions_response = 42;
ApplyCompletionAdditionalEdits apply_completion_additional_edits = 41; ApplyCompletionAdditionalEdits apply_completion_additional_edits = 43;
ApplyCompletionAdditionalEditsResponse apply_completion_additional_edits_response = 42; ApplyCompletionAdditionalEditsResponse apply_completion_additional_edits_response = 44;
GetCodeActions get_code_actions = 43; GetCodeActions get_code_actions = 45;
GetCodeActionsResponse get_code_actions_response = 44; GetCodeActionsResponse get_code_actions_response = 46;
ApplyCodeAction apply_code_action = 45; ApplyCodeAction apply_code_action = 47;
ApplyCodeActionResponse apply_code_action_response = 46; ApplyCodeActionResponse apply_code_action_response = 48;
PrepareRename prepare_rename = 47; PrepareRename prepare_rename = 49;
PrepareRenameResponse prepare_rename_response = 48; PrepareRenameResponse prepare_rename_response = 50;
PerformRename perform_rename = 49; PerformRename perform_rename = 51;
PerformRenameResponse perform_rename_response = 50; PerformRenameResponse perform_rename_response = 52;
GetChannels get_channels = 51; GetChannels get_channels = 53;
GetChannelsResponse get_channels_response = 52; GetChannelsResponse get_channels_response = 54;
JoinChannel join_channel = 53; JoinChannel join_channel = 55;
JoinChannelResponse join_channel_response = 54; JoinChannelResponse join_channel_response = 56;
LeaveChannel leave_channel = 55; LeaveChannel leave_channel = 57;
SendChannelMessage send_channel_message = 56; SendChannelMessage send_channel_message = 58;
SendChannelMessageResponse send_channel_message_response = 57; SendChannelMessageResponse send_channel_message_response = 59;
ChannelMessageSent channel_message_sent = 58; ChannelMessageSent channel_message_sent = 60;
GetChannelMessages get_channel_messages = 59; GetChannelMessages get_channel_messages = 61;
GetChannelMessagesResponse get_channel_messages_response = 60; GetChannelMessagesResponse get_channel_messages_response = 62;
UpdateContacts update_contacts = 61; UpdateContacts update_contacts = 63;
GetUsers get_users = 62; GetUsers get_users = 64;
GetUsersResponse get_users_response = 63; GetUsersResponse get_users_response = 65;
} }
} }
@ -179,13 +181,22 @@ message GetProjectSymbols {
} }
message GetProjectSymbolsResponse { message GetProjectSymbolsResponse {
repeated string languages = 1; repeated Symbol symbols = 4;
repeated uint64 symbol_counts_per_language = 2;
repeated Symbol symbols = 3;
} }
message Symbol { message Symbol {
bytes lsp_symbol = 1; uint64 worktree_id = 1;
string language_name = 2;
bytes lsp_symbol = 3;
}
message OpenBufferForSymbol {
uint64 project_id = 1;
Symbol symbol = 2;
}
message OpenBufferForSymbolResponse {
Buffer buffer = 1;
} }
message OpenBuffer { message OpenBuffer {

View file

@ -158,7 +158,7 @@ messages!(
(GetDefinition, Foreground), (GetDefinition, Foreground),
(GetDefinitionResponse, Foreground), (GetDefinitionResponse, Foreground),
(GetProjectSymbols, Background), (GetProjectSymbols, Background),
(GetProjectSymbolsResponse, Foreground), (GetProjectSymbolsResponse, Background),
(GetUsers, Foreground), (GetUsers, Foreground),
(GetUsersResponse, Foreground), (GetUsersResponse, Foreground),
(JoinChannel, Foreground), (JoinChannel, Foreground),
@ -168,6 +168,8 @@ messages!(
(LeaveChannel, Foreground), (LeaveChannel, Foreground),
(LeaveProject, Foreground), (LeaveProject, Foreground),
(OpenBuffer, Foreground), (OpenBuffer, Foreground),
(OpenBufferForSymbol, Foreground),
(OpenBufferForSymbolResponse, Foreground),
(OpenBufferResponse, Foreground), (OpenBufferResponse, Foreground),
(PerformRename, Background), (PerformRename, Background),
(PerformRenameResponse, Background), (PerformRenameResponse, Background),
@ -211,6 +213,7 @@ request_messages!(
(JoinChannel, JoinChannelResponse), (JoinChannel, JoinChannelResponse),
(JoinProject, JoinProjectResponse), (JoinProject, JoinProjectResponse),
(OpenBuffer, OpenBufferResponse), (OpenBuffer, OpenBufferResponse),
(OpenBufferForSymbol, OpenBufferForSymbolResponse),
(Ping, Ack), (Ping, Ack),
(PerformRename, PerformRenameResponse), (PerformRename, PerformRenameResponse),
(PrepareRename, PrepareRenameResponse), (PrepareRename, PrepareRenameResponse),
@ -243,6 +246,7 @@ entity_messages!(
JoinProject, JoinProject,
LeaveProject, LeaveProject,
OpenBuffer, OpenBuffer,
OpenBufferForSymbol,
PerformRename, PerformRename,
PrepareRename, PrepareRename,
RemoveProjectCollaborator, RemoveProjectCollaborator,

View file

@ -80,6 +80,7 @@ impl Server {
.add_message_handler(Server::disk_based_diagnostics_updated) .add_message_handler(Server::disk_based_diagnostics_updated)
.add_request_handler(Server::get_definition) .add_request_handler(Server::get_definition)
.add_request_handler(Server::get_project_symbols) .add_request_handler(Server::get_project_symbols)
.add_request_handler(Server::open_buffer_for_symbol)
.add_request_handler(Server::open_buffer) .add_request_handler(Server::open_buffer)
.add_message_handler(Server::close_buffer) .add_message_handler(Server::close_buffer)
.add_request_handler(Server::update_buffer) .add_request_handler(Server::update_buffer)
@ -602,6 +603,20 @@ impl Server {
.await?) .await?)
} }
async fn open_buffer_for_symbol(
self: Arc<Server>,
request: TypedEnvelope<proto::OpenBufferForSymbol>,
) -> tide::Result<proto::OpenBufferForSymbolResponse> {
let host_connection_id = self
.state()
.read_project(request.payload.project_id, request.sender_id)?
.host_connection_id;
Ok(self
.peer
.forward_request(request.sender_id, host_connection_id, request.payload)
.await?)
}
async fn open_buffer( async fn open_buffer(
self: Arc<Server>, self: Arc<Server>,
request: TypedEnvelope<proto::OpenBuffer>, request: TypedEnvelope<proto::OpenBuffer>,