project: Handle capabilities parse for more methods when registerOptions doesn't exist (#36984)

Smit Barmase created

Closes #36938

Follow up to https://github.com/zed-industries/zed/pull/36554

When `registerOptions` is `None`, we should fall back instead of
skipping capability registration.

1. `Option<OneOf<bool, T>>`, where `T` is struct – handled in the
attached PR ✅
2. `Option<T>`, where `T` is an enum that can be `Simple(bool)` or
`Options(S)` – this PR ✅
3. `Option<T>`, where `T` is struct – we should fall back to default
values for these options ⚠️

Release Notes:

- Fixed an issue where hover popovers would not appear in language
servers like Java.

Change summary

crates/project/src/lsp_store.rs | 58 ++++++++++++++++------------------
1 file changed, 27 insertions(+), 31 deletions(-)

Detailed changes

crates/project/src/lsp_store.rs 🔗

@@ -11778,17 +11778,15 @@ impl LspStore {
                     notify_server_capabilities_updated(&server, cx);
                 }
                 "textDocument/codeAction" => {
-                    if let Some(options) = reg
-                        .register_options
-                        .map(serde_json::from_value)
-                        .transpose()?
-                    {
-                        server.update_capabilities(|capabilities| {
-                            capabilities.code_action_provider =
-                                Some(lsp::CodeActionProviderCapability::Options(options));
-                        });
-                        notify_server_capabilities_updated(&server, cx);
-                    }
+                    let options = parse_register_capabilities(reg)?;
+                    let provider = match options {
+                        OneOf::Left(value) => lsp::CodeActionProviderCapability::Simple(value),
+                        OneOf::Right(caps) => caps,
+                    };
+                    server.update_capabilities(|capabilities| {
+                        capabilities.code_action_provider = Some(provider);
+                    });
+                    notify_server_capabilities_updated(&server, cx);
                 }
                 "textDocument/definition" => {
                     let options = parse_register_capabilities(reg)?;
@@ -11810,16 +11808,15 @@ impl LspStore {
                     }
                 }
                 "textDocument/hover" => {
-                    if let Some(caps) = reg
-                        .register_options
-                        .map(serde_json::from_value)
-                        .transpose()?
-                    {
-                        server.update_capabilities(|capabilities| {
-                            capabilities.hover_provider = Some(caps);
-                        });
-                        notify_server_capabilities_updated(&server, cx);
-                    }
+                    let options = parse_register_capabilities(reg)?;
+                    let provider = match options {
+                        OneOf::Left(value) => lsp::HoverProviderCapability::Simple(value),
+                        OneOf::Right(caps) => caps,
+                    };
+                    server.update_capabilities(|capabilities| {
+                        capabilities.hover_provider = Some(provider);
+                    });
+                    notify_server_capabilities_updated(&server, cx);
                 }
                 "textDocument/signatureHelp" => {
                     if let Some(caps) = reg
@@ -11904,16 +11901,15 @@ impl LspStore {
                     }
                 }
                 "textDocument/documentColor" => {
-                    if let Some(caps) = reg
-                        .register_options
-                        .map(serde_json::from_value)
-                        .transpose()?
-                    {
-                        server.update_capabilities(|capabilities| {
-                            capabilities.color_provider = Some(caps);
-                        });
-                        notify_server_capabilities_updated(&server, cx);
-                    }
+                    let options = parse_register_capabilities(reg)?;
+                    let provider = match options {
+                        OneOf::Left(value) => lsp::ColorProviderCapability::Simple(value),
+                        OneOf::Right(caps) => caps,
+                    };
+                    server.update_capabilities(|capabilities| {
+                        capabilities.color_provider = Some(provider);
+                    });
+                    notify_server_capabilities_updated(&server, cx);
                 }
                 _ => log::warn!("unhandled capability registration: {reg:?}"),
             }