mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-05 10:20:51 +00:00
Update LSP to the newest version (#2535)
Current `lsp-types:0.91.1` crate lacks inlay hints' definitions. Crate's changelog is not very descriptive, but it appears that `0.92.1` could be used: https://github.com/gluon-lang/lsp-types/blob/master/CHANGELOG.md#v0921-2022-03-21 The latest is crate version is `0.94.0` (2023-02-08), the PR updates Zed to the latest version. Notable changes: * workspace symbols may arrive unresolved if the corresponding client capability is enabled: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#partialResults Zed has this capability disabled, forcing all symbols to arrive synchronously (?). Resolve capabilities are important for inlay hints too, but I've not found any code in Zed for that outside tests, so I'd love to learn more and implement the resolution for workspace symbols separately. * since LSP `3.17` (current), watch file changes can use relative glob patterns: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_didChangeWatchedFiles That seemed just a straightforward extra `match` to use the same Ruse `Glob` to handle the relative path one. Release Notes: N/A
This commit is contained in:
commit
986b02e217
8 changed files with 105 additions and 71 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -3744,9 +3744,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "lsp-types"
|
||||
version = "0.91.1"
|
||||
version = "0.94.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2368312c59425dd133cb9a327afee65be0a633a8ce471d248e2202a48f8f68ae"
|
||||
checksum = "0b63735a13a1f9cd4f4835223d828ed9c2e35c8c5e61837774399f558b6a1237"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"serde",
|
||||
|
|
|
@ -5010,19 +5010,21 @@ async fn test_project_symbols(
|
|||
.unwrap();
|
||||
|
||||
let fake_language_server = fake_language_servers.next().await.unwrap();
|
||||
fake_language_server.handle_request::<lsp::request::WorkspaceSymbol, _, _>(|_, _| async move {
|
||||
#[allow(deprecated)]
|
||||
Ok(Some(vec![lsp::SymbolInformation {
|
||||
name: "TWO".into(),
|
||||
location: lsp::Location {
|
||||
uri: lsp::Url::from_file_path("/code/crate-2/two.rs").unwrap(),
|
||||
range: lsp::Range::new(lsp::Position::new(0, 6), lsp::Position::new(0, 9)),
|
||||
fake_language_server.handle_request::<lsp::WorkspaceSymbolRequest, _, _>(|_, _| async move {
|
||||
Ok(Some(lsp::WorkspaceSymbolResponse::Flat(vec![
|
||||
#[allow(deprecated)]
|
||||
lsp::SymbolInformation {
|
||||
name: "TWO".into(),
|
||||
location: lsp::Location {
|
||||
uri: lsp::Url::from_file_path("/code/crate-2/two.rs").unwrap(),
|
||||
range: lsp::Range::new(lsp::Position::new(0, 6), lsp::Position::new(0, 9)),
|
||||
},
|
||||
kind: lsp::SymbolKind::CONSTANT,
|
||||
tags: None,
|
||||
container_name: None,
|
||||
deprecated: None,
|
||||
},
|
||||
kind: lsp::SymbolKind::CONSTANT,
|
||||
tags: None,
|
||||
container_name: None,
|
||||
deprecated: None,
|
||||
}]))
|
||||
])))
|
||||
});
|
||||
|
||||
// Request the definition of a symbol as the guest.
|
||||
|
|
|
@ -20,7 +20,7 @@ anyhow.workspace = true
|
|||
async-pipe = { git = "https://github.com/zed-industries/async-pipe-rs", rev = "82d00a04211cf4e1236029aa03e6b6ce2a74c553", optional = true }
|
||||
futures.workspace = true
|
||||
log.workspace = true
|
||||
lsp-types = "0.91"
|
||||
lsp-types = "0.94"
|
||||
parking_lot.workspace = true
|
||||
postage.workspace = true
|
||||
serde.workspace = true
|
||||
|
|
|
@ -361,13 +361,18 @@ impl LanguageServer {
|
|||
capabilities: ClientCapabilities {
|
||||
workspace: Some(WorkspaceClientCapabilities {
|
||||
configuration: Some(true),
|
||||
did_change_watched_files: Some(DynamicRegistrationClientCapabilities {
|
||||
did_change_watched_files: Some(DidChangeWatchedFilesClientCapabilities {
|
||||
dynamic_registration: Some(true),
|
||||
relative_pattern_support: Some(true),
|
||||
}),
|
||||
did_change_configuration: Some(DynamicRegistrationClientCapabilities {
|
||||
dynamic_registration: Some(true),
|
||||
}),
|
||||
workspace_folders: Some(true),
|
||||
symbol: Some(WorkspaceSymbolClientCapabilities {
|
||||
resolve_support: None,
|
||||
..WorkspaceSymbolClientCapabilities::default()
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
text_document: Some(TextDocumentClientCapabilities {
|
||||
|
|
|
@ -1524,6 +1524,7 @@ impl LspCommand for GetCodeActions {
|
|||
context: lsp::CodeActionContext {
|
||||
diagnostics: relevant_diagnostics,
|
||||
only: language_server.code_action_kinds(),
|
||||
..lsp::CodeActionContext::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ use language::{
|
|||
PendingLanguageServer, PointUtf16, RopeFingerprint, TextBufferSnapshot, ToOffset, ToPointUtf16,
|
||||
Transaction, Unclipped,
|
||||
};
|
||||
use log::error;
|
||||
use lsp::{
|
||||
DiagnosticSeverity, DiagnosticTag, DidChangeWatchedFilesRegistrationOptions,
|
||||
DocumentHighlightKind, LanguageServer, LanguageServerId,
|
||||
|
@ -3017,10 +3018,12 @@ impl Project {
|
|||
if let Some(worktree) = worktree.upgrade(cx) {
|
||||
let worktree = worktree.read(cx);
|
||||
if let Some(abs_path) = worktree.abs_path().to_str() {
|
||||
if let Some(suffix) = watcher
|
||||
.glob_pattern
|
||||
.strip_prefix(abs_path)
|
||||
.and_then(|s| s.strip_prefix(std::path::MAIN_SEPARATOR))
|
||||
if let Some(suffix) = match &watcher.glob_pattern {
|
||||
lsp::GlobPattern::String(s) => s,
|
||||
lsp::GlobPattern::Relative(rp) => &rp.pattern,
|
||||
}
|
||||
.strip_prefix(abs_path)
|
||||
.and_then(|s| s.strip_prefix(std::path::MAIN_SEPARATOR))
|
||||
{
|
||||
if let Some(glob) = Glob::new(suffix).log_err() {
|
||||
builders
|
||||
|
@ -3759,7 +3762,7 @@ impl Project {
|
|||
let worktree_abs_path = worktree.abs_path().clone();
|
||||
requests.push(
|
||||
server
|
||||
.request::<lsp::request::WorkspaceSymbol>(
|
||||
.request::<lsp::request::WorkspaceSymbolRequest>(
|
||||
lsp::WorkspaceSymbolParams {
|
||||
query: query.to_string(),
|
||||
..Default::default()
|
||||
|
@ -3767,12 +3770,32 @@ impl Project {
|
|||
)
|
||||
.log_err()
|
||||
.map(move |response| {
|
||||
let lsp_symbols = response.flatten().map(|symbol_response| match symbol_response {
|
||||
lsp::WorkspaceSymbolResponse::Flat(flat_responses) => {
|
||||
flat_responses.into_iter().map(|lsp_symbol| {
|
||||
(lsp_symbol.name, lsp_symbol.kind, lsp_symbol.location)
|
||||
}).collect::<Vec<_>>()
|
||||
}
|
||||
lsp::WorkspaceSymbolResponse::Nested(nested_responses) => {
|
||||
nested_responses.into_iter().filter_map(|lsp_symbol| {
|
||||
let location = match lsp_symbol.location {
|
||||
lsp::OneOf::Left(location) => location,
|
||||
lsp::OneOf::Right(_) => {
|
||||
error!("Unexpected: client capabilities forbid symbol resolutions in workspace.symbol.resolveSupport");
|
||||
return None
|
||||
}
|
||||
};
|
||||
Some((lsp_symbol.name, lsp_symbol.kind, location))
|
||||
}).collect::<Vec<_>>()
|
||||
}
|
||||
}).unwrap_or_default();
|
||||
|
||||
(
|
||||
adapter,
|
||||
language,
|
||||
worktree_id,
|
||||
worktree_abs_path,
|
||||
response.unwrap_or_default(),
|
||||
lsp_symbols,
|
||||
)
|
||||
}),
|
||||
);
|
||||
|
@ -3794,53 +3817,54 @@ impl Project {
|
|||
adapter_language,
|
||||
source_worktree_id,
|
||||
worktree_abs_path,
|
||||
response,
|
||||
lsp_symbols,
|
||||
) in responses
|
||||
{
|
||||
symbols.extend(response.into_iter().flatten().filter_map(|lsp_symbol| {
|
||||
let abs_path = lsp_symbol.location.uri.to_file_path().ok()?;
|
||||
let mut worktree_id = source_worktree_id;
|
||||
let path;
|
||||
if let Some((worktree, rel_path)) =
|
||||
this.find_local_worktree(&abs_path, cx)
|
||||
{
|
||||
worktree_id = worktree.read(cx).id();
|
||||
path = rel_path;
|
||||
} else {
|
||||
path = relativize_path(&worktree_abs_path, &abs_path);
|
||||
}
|
||||
|
||||
let project_path = ProjectPath {
|
||||
worktree_id,
|
||||
path: path.into(),
|
||||
};
|
||||
let signature = this.symbol_signature(&project_path);
|
||||
let adapter_language = adapter_language.clone();
|
||||
let language = this
|
||||
.languages
|
||||
.language_for_file(&project_path.path, None)
|
||||
.unwrap_or_else(move |_| adapter_language);
|
||||
let language_server_name = adapter.name.clone();
|
||||
Some(async move {
|
||||
let language = language.await;
|
||||
let label = language
|
||||
.label_for_symbol(&lsp_symbol.name, lsp_symbol.kind)
|
||||
.await;
|
||||
|
||||
Symbol {
|
||||
language_server_name,
|
||||
source_worktree_id,
|
||||
path: project_path,
|
||||
label: label.unwrap_or_else(|| {
|
||||
CodeLabel::plain(lsp_symbol.name.clone(), None)
|
||||
}),
|
||||
kind: lsp_symbol.kind,
|
||||
name: lsp_symbol.name,
|
||||
range: range_from_lsp(lsp_symbol.location.range),
|
||||
signature,
|
||||
symbols.extend(lsp_symbols.into_iter().filter_map(
|
||||
|(symbol_name, symbol_kind, symbol_location)| {
|
||||
let abs_path = symbol_location.uri.to_file_path().ok()?;
|
||||
let mut worktree_id = source_worktree_id;
|
||||
let path;
|
||||
if let Some((worktree, rel_path)) =
|
||||
this.find_local_worktree(&abs_path, cx)
|
||||
{
|
||||
worktree_id = worktree.read(cx).id();
|
||||
path = rel_path;
|
||||
} else {
|
||||
path = relativize_path(&worktree_abs_path, &abs_path);
|
||||
}
|
||||
})
|
||||
}));
|
||||
|
||||
let project_path = ProjectPath {
|
||||
worktree_id,
|
||||
path: path.into(),
|
||||
};
|
||||
let signature = this.symbol_signature(&project_path);
|
||||
let adapter_language = adapter_language.clone();
|
||||
let language = this
|
||||
.languages
|
||||
.language_for_file(&project_path.path, None)
|
||||
.unwrap_or_else(move |_| adapter_language);
|
||||
let language_server_name = adapter.name.clone();
|
||||
Some(async move {
|
||||
let language = language.await;
|
||||
let label =
|
||||
language.label_for_symbol(&symbol_name, symbol_kind).await;
|
||||
|
||||
Symbol {
|
||||
language_server_name,
|
||||
source_worktree_id,
|
||||
path: project_path,
|
||||
label: label.unwrap_or_else(|| {
|
||||
CodeLabel::plain(symbol_name.clone(), None)
|
||||
}),
|
||||
kind: symbol_kind,
|
||||
name: symbol_name,
|
||||
range: range_from_lsp(symbol_location.range),
|
||||
signature,
|
||||
}
|
||||
})
|
||||
},
|
||||
));
|
||||
}
|
||||
symbols
|
||||
});
|
||||
|
@ -5850,7 +5874,7 @@ impl Project {
|
|||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
let Some(guest_id) = envelope.original_sender_id else {
|
||||
log::error!("missing original_sender_id on SynchronizeBuffers request");
|
||||
error!("missing original_sender_id on SynchronizeBuffers request");
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -506,7 +506,9 @@ async fn test_reporting_fs_changes_to_language_servers(cx: &mut gpui::TestAppCon
|
|||
register_options: serde_json::to_value(
|
||||
lsp::DidChangeWatchedFilesRegistrationOptions {
|
||||
watchers: vec![lsp::FileSystemWatcher {
|
||||
glob_pattern: "/the-root/*.{rs,c}".to_string(),
|
||||
glob_pattern: lsp::GlobPattern::String(
|
||||
"/the-root/*.{rs,c}".to_string(),
|
||||
),
|
||||
kind: None,
|
||||
}],
|
||||
},
|
||||
|
|
|
@ -284,7 +284,7 @@ mod tests {
|
|||
symbol("uno", "/dir/test.rs"),
|
||||
];
|
||||
let fake_server = fake_servers.next().await.unwrap();
|
||||
fake_server.handle_request::<lsp::request::WorkspaceSymbol, _, _>(
|
||||
fake_server.handle_request::<lsp::WorkspaceSymbolRequest, _, _>(
|
||||
move |params: lsp::WorkspaceSymbolParams, cx| {
|
||||
let executor = cx.background();
|
||||
let fake_symbols = fake_symbols.clone();
|
||||
|
@ -308,12 +308,12 @@ mod tests {
|
|||
.await
|
||||
};
|
||||
|
||||
Ok(Some(
|
||||
Ok(Some(lsp::WorkspaceSymbolResponse::Flat(
|
||||
matches
|
||||
.into_iter()
|
||||
.map(|mat| fake_symbols[mat.candidate_id].clone())
|
||||
.collect(),
|
||||
))
|
||||
)))
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue