Update LSP to the newest version

Kirill Bulatov created

Change summary

Cargo.lock                                    |   4 
crates/collab/src/tests/integration_tests.rs  |  26 ++--
crates/lsp/Cargo.toml                         |   2 
crates/lsp/src/lsp.rs                         |   7 +
crates/project/src/lsp_command.rs             |   1 
crates/project/src/project.rs                 | 126 ++++++++++++--------
crates/project/src/project_tests.rs           |   4 
crates/project_symbols/src/project_symbols.rs |   6 
8 files changed, 105 insertions(+), 71 deletions(-)

Detailed changes

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",

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::<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.

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

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 {

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()
             },
         }
     }

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::<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;
             };
 

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,
                         }],
                     },

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::<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(),
-                    ))
+                    )))
                 }
             },
         );