Don't serialize the full LSP symbol when collaborating

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Antonio Scandurra 2022-02-22 18:08:43 +01:00
parent 72ad3c2897
commit fad335b2ba
7 changed files with 68 additions and 55 deletions

1
Cargo.lock generated
View file

@ -3567,7 +3567,6 @@ dependencies = [
"editor",
"fuzzy",
"gpui",
"language",
"ordered-float",
"postage",
"project",

View file

@ -80,7 +80,7 @@ pub trait LspExt: 'static + Send + Sync {
fn label_for_completion(&self, _: &lsp::CompletionItem, _: &Language) -> Option<CodeLabel> {
None
}
fn label_for_symbol(&self, _: &lsp::SymbolInformation, _: &Language) -> Option<CodeLabel> {
fn label_for_symbol(&self, _: &str, _: lsp::SymbolKind, _: &Language) -> Option<CodeLabel> {
None
}
}
@ -435,8 +435,8 @@ impl Language {
.label_for_completion(completion, self)
}
pub fn label_for_symbol(&self, symbol: &lsp::SymbolInformation) -> Option<CodeLabel> {
self.lsp_ext.as_ref()?.label_for_symbol(symbol, self)
pub fn label_for_symbol(&self, name: &str, kind: lsp::SymbolKind) -> Option<CodeLabel> {
self.lsp_ext.as_ref()?.label_for_symbol(name, kind, self)
}
pub fn highlight_text<'a>(

View file

@ -24,6 +24,7 @@ use postage::{broadcast, prelude::Stream, sink::Sink, watch};
use smol::block_on;
use std::{
convert::TryInto,
mem,
ops::Range,
path::{Component, Path, PathBuf},
sync::{atomic::AtomicBool, Arc},
@ -125,7 +126,9 @@ pub struct Symbol {
pub language_name: String,
pub path: PathBuf,
pub label: CodeLabel,
pub lsp_symbol: lsp::SymbolInformation,
pub name: String,
pub kind: lsp::SymbolKind,
pub range: Range<PointUtf16>,
}
#[derive(Default)]
@ -1281,18 +1284,21 @@ impl Project {
path = relativize_path(&worktree_abs_path, &abs_path);
}
let label =
language.label_for_symbol(&lsp_symbol).unwrap_or_else(
|| CodeLabel::plain(lsp_symbol.name.clone(), None),
);
let label = language
.label_for_symbol(&lsp_symbol.name, lsp_symbol.kind)
.unwrap_or_else(|| {
CodeLabel::plain(lsp_symbol.name.clone(), None)
});
Some(Symbol {
source_worktree_id,
worktree_id,
language_name: language.name().to_string(),
name: lsp_symbol.name,
kind: lsp_symbol.kind,
label,
path,
lsp_symbol,
range: range_from_lsp(lsp_symbol.location.range),
})
},
));
@ -2896,16 +2902,24 @@ impl Project {
let language = self
.languages
.get_language(&serialized_symbol.language_name);
let lsp_symbol = serde_json::from_slice(&serialized_symbol.lsp_symbol)?;
let start = serialized_symbol
.start
.ok_or_else(|| anyhow!("invalid start"))?;
let end = serialized_symbol
.end
.ok_or_else(|| anyhow!("invalid end"))?;
let kind = unsafe { mem::transmute(serialized_symbol.kind) };
Ok(Symbol {
source_worktree_id: WorktreeId::from_proto(serialized_symbol.source_worktree_id),
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)),
.and_then(|language| language.label_for_symbol(&serialized_symbol.name, kind))
.unwrap_or_else(|| CodeLabel::plain(serialized_symbol.name.clone(), None)),
name: serialized_symbol.name,
path: PathBuf::from(serialized_symbol.path),
lsp_symbol,
range: PointUtf16::new(start.row, start.column)..PointUtf16::new(end.row, end.column),
kind,
})
}
@ -3195,8 +3209,17 @@ fn serialize_symbol(symbol: &Symbol) -> proto::Symbol {
source_worktree_id: symbol.source_worktree_id.to_proto(),
worktree_id: symbol.worktree_id.to_proto(),
language_name: symbol.language_name.clone(),
name: symbol.name.clone(),
kind: unsafe { mem::transmute(symbol.kind) },
path: symbol.path.to_string_lossy().to_string(),
lsp_symbol: serde_json::to_vec(&symbol.lsp_symbol).unwrap(),
start: Some(proto::Point {
row: symbol.range.start.row,
column: symbol.range.start.column,
}),
end: Some(proto::Point {
row: symbol.range.end.row,
column: symbol.range.end.column,
}),
}
}

View file

@ -10,7 +10,6 @@ path = "src/project_symbols.rs"
editor = { path = "../editor" }
fuzzy = { path = "../fuzzy" }
gpui = { path = "../gpui" }
language = { path = "../language" }
project = { path = "../project" }
text = { path = "../text" }
workspace = { path = "../workspace" }

View file

@ -10,7 +10,6 @@ use gpui::{
AppContext, Axis, Entity, ModelHandle, MutableAppContext, RenderContext, Task, View,
ViewContext, ViewHandle, WeakViewHandle,
};
use language::range_from_lsp;
use ordered_float::OrderedFloat;
use postage::watch;
use project::{Project, Symbol};
@ -358,14 +357,13 @@ impl ProjectSymbolsView {
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);
start = buffer.clip_point_utf16(symbol.range.start, Bias::Left);
end = buffer.clip_point_utf16(symbol.range.end, Bias::Left);
}
let editor = workspace.open_item(BufferItemHandle(buffer), cx);

View file

@ -188,8 +188,11 @@ message Symbol {
uint64 source_worktree_id = 1;
uint64 worktree_id = 2;
string language_name = 3;
string path = 4;
bytes lsp_symbol = 5;
string name = 4;
int32 kind = 5;
string path = 6;
Point start = 7;
Point end = 8;
}
message OpenBufferForSymbol {
@ -620,6 +623,11 @@ message Range {
uint64 end = 2;
}
message Point {
uint32 row = 1;
uint32 column = 2;
}
message Nonce {
uint64 upper_half = 1;
uint64 lower_half = 2;

View file

@ -233,49 +233,50 @@ impl LspExt for RustLsp {
fn label_for_symbol(
&self,
symbol: &lsp::SymbolInformation,
name: &str,
kind: lsp::SymbolKind,
language: &Language,
) -> Option<CodeLabel> {
let (text, filter_range, display_range) = match symbol.kind {
let (text, filter_range, display_range) = match kind {
lsp::SymbolKind::METHOD | lsp::SymbolKind::FUNCTION => {
let text = format!("fn {} () {{}}", symbol.name);
let filter_range = 3..3 + symbol.name.len();
let text = format!("fn {} () {{}}", name);
let filter_range = 3..3 + name.len();
let display_range = 0..filter_range.end;
(text, filter_range, display_range)
}
lsp::SymbolKind::STRUCT => {
let text = format!("struct {} {{}}", symbol.name);
let filter_range = 7..7 + symbol.name.len();
let text = format!("struct {} {{}}", name);
let filter_range = 7..7 + name.len();
let display_range = 0..filter_range.end;
(text, filter_range, display_range)
}
lsp::SymbolKind::ENUM => {
let text = format!("enum {} {{}}", symbol.name);
let filter_range = 5..5 + symbol.name.len();
let text = format!("enum {} {{}}", name);
let filter_range = 5..5 + name.len();
let display_range = 0..filter_range.end;
(text, filter_range, display_range)
}
lsp::SymbolKind::INTERFACE => {
let text = format!("trait {} {{}}", symbol.name);
let filter_range = 6..6 + symbol.name.len();
let text = format!("trait {} {{}}", name);
let filter_range = 6..6 + name.len();
let display_range = 0..filter_range.end;
(text, filter_range, display_range)
}
lsp::SymbolKind::CONSTANT => {
let text = format!("const {}: () = ();", symbol.name);
let filter_range = 6..6 + symbol.name.len();
let text = format!("const {}: () = ();", name);
let filter_range = 6..6 + name.len();
let display_range = 0..filter_range.end;
(text, filter_range, display_range)
}
lsp::SymbolKind::MODULE => {
let text = format!("mod {} {{}}", symbol.name);
let filter_range = 4..4 + symbol.name.len();
let text = format!("mod {} {{}}", name);
let filter_range = 4..4 + name.len();
let display_range = 0..filter_range.end;
(text, filter_range, display_range)
}
lsp::SymbolKind::TYPE_PARAMETER => {
let text = format!("type {} {{}}", symbol.name);
let filter_range = 5..5 + symbol.name.len();
let text = format!("type {} {{}}", name);
let filter_range = 5..5 + name.len();
let display_range = 0..filter_range.end;
(text, filter_range, display_range)
}
@ -456,7 +457,6 @@ mod tests {
}
#[test]
#[allow(deprecated)]
fn test_rust_label_for_symbol() {
let language = rust();
let grammar = language.grammar().unwrap();
@ -474,14 +474,7 @@ mod tests {
let highlight_keyword = grammar.highlight_id_for_name("keyword").unwrap();
assert_eq!(
language.label_for_symbol(&lsp::SymbolInformation {
kind: lsp::SymbolKind::FUNCTION,
name: "hello".to_string(),
location: lsp::Location::new("file://a".parse().unwrap(), Default::default()),
container_name: Default::default(),
deprecated: Default::default(),
tags: Default::default(),
}),
language.label_for_symbol("hello", lsp::SymbolKind::FUNCTION),
Some(CodeLabel {
text: "fn hello".to_string(),
filter_range: 3..8,
@ -490,14 +483,7 @@ mod tests {
);
assert_eq!(
language.label_for_symbol(&lsp::SymbolInformation {
kind: lsp::SymbolKind::TYPE_PARAMETER,
name: "World".to_string(),
location: lsp::Location::new("file://a".parse().unwrap(), Default::default()),
container_name: Default::default(),
deprecated: Default::default(),
tags: Default::default(),
}),
language.label_for_symbol("World", lsp::SymbolKind::TYPE_PARAMETER),
Some(CodeLabel {
text: "type World".to_string(),
filter_range: 5..10,