diff --git a/Cargo.lock b/Cargo.lock index 95fcf2224d..3537056373 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index d771f969d8..8e2ff0d277 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -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::(|_, _| 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::(|_, _| 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. diff --git a/crates/lsp/Cargo.toml b/crates/lsp/Cargo.toml index c766dacd2a..47e0995c85 100644 --- a/crates/lsp/Cargo.toml +++ b/crates/lsp/Cargo.toml @@ -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 diff --git a/crates/lsp/src/lsp.rs b/crates/lsp/src/lsp.rs index 2ec1f63b8b..1b01660308 100644 --- a/crates/lsp/src/lsp.rs +++ b/crates/lsp/src/lsp.rs @@ -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 { diff --git a/crates/project/src/lsp_command.rs b/crates/project/src/lsp_command.rs index 5ee6443896..ce7004dd31 100644 --- a/crates/project/src/lsp_command.rs +++ b/crates/project/src/lsp_command.rs @@ -1524,6 +1524,7 @@ impl LspCommand for GetCodeActions { context: lsp::CodeActionContext { diagnostics: relevant_diagnostics, only: language_server.code_action_kinds(), + ..lsp::CodeActionContext::default() }, } } diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 92210a75a8..de4cd82160 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -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::( + .request::( 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::>() + } + 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::>() + } + }).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; }; diff --git a/crates/project/src/project_tests.rs b/crates/project/src/project_tests.rs index 34b63fd5bd..656fdaf25d 100644 --- a/crates/project/src/project_tests.rs +++ b/crates/project/src/project_tests.rs @@ -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, }], }, diff --git a/crates/project_symbols/src/project_symbols.rs b/crates/project_symbols/src/project_symbols.rs index 992283df01..71271d4e7c 100644 --- a/crates/project_symbols/src/project_symbols.rs +++ b/crates/project_symbols/src/project_symbols.rs @@ -284,7 +284,7 @@ mod tests { symbol("uno", "/dir/test.rs"), ]; let fake_server = fake_servers.next().await.unwrap(); - fake_server.handle_request::( + fake_server.handle_request::( 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(), - )) + ))) } }, );