Skip to content

Document non-hierarchical symbols not working for helix editorΒ #459

Description

@blthayer

I did generate this with AI (after "AI generated report follows" below), but spot-checked the code it called out, and it seems to be accurate, especially after guiding it in the right direction (although admittedly I am lacking larger context beyond the code areas that look to be the culprit). My apologies if I'm off here.

When using helix and opening the document symbol picker, I get nothing. I ran helix with -vvv and set ZUBAN_LOG to debug, and had an AI agent peruse the helix log, zuban log, and source code for both projects.

As someone not deep in the LSP development space (just a casual user πŸ˜„ ), it's not obvious to me if this is a helix problem or a zuban problem. My read of the situation is zuban only support hierarchical symbols, but helix advertises that it does not support hierarchical symbols (but maybe does support them since it does its own flattening internally? See also: helix-editor/helix#5048). So I guess at the very least consider this answering the comment in zuban "until I find a client that does..."

Locally, I made the following patch and built zuban from source (cargo build --release --bin zuban). After replacing the zuban binary in my Python virtual environment with this one, my symbol picker in helix works.

➜  zuban git:(master) βœ— git log --oneline | head
eb1aaf55e chore: Release
5828cb31d Make a zuban typeshed path lookup possible for pip install -t
508a5c990 Revert "try building sdist with maturin-action"
d1edb3d62 chore: Release
eb5148092 Add a way to recover why a file is ignored
049fbdf72 Change the slightly to be per text document
fce5b1857 Add a status field
71ee0a8ec Make some logs a bit noisier
06043e956 Add a log about initialization options
d9da4ad5e Implement disableLanguageServices
➜  zuban git:(master) βœ— git --no-pager diff
diff --git a/crates/zubanls/src/capabilities.rs b/crates/zubanls/src/capabilities.rs
index e053fab47..f42040cdd 100644
--- a/crates/zubanls/src/capabilities.rs
+++ b/crates/zubanls/src/capabilities.rs
@@ -225,6 +225,7 @@ impl ClientCapabilities {
         .unwrap_or_default()
     }

+    #[expect(dead_code)]
     pub(crate) fn hierarchical_symbols(&self) -> bool {
         (|| {
             self.caps
diff --git a/crates/zubanls/src/request_handlers.rs b/crates/zubanls/src/request_handlers.rs
index 37ecb0c23..b5f189ff9 100644
--- a/crates/zubanls/src/request_handlers.rs
+++ b/crates/zubanls/src/request_handlers.rs
@@ -537,13 +537,6 @@ impl GlobalState<'_> {
             params.text_document.uri.as_str(),
         );
         let encoding = self.client_capabilities.negotiated_encoding();
-        let hierarchical_symbols = self.client_capabilities.hierarchical_symbols();
-        if !hierarchical_symbols {
-            // This is not supported for now, VSCode supports doesn't do it that way and until I
-            // find a client that does I won't implement it.
-            return Ok(None);
-        }
-
         let document = self.document(&params.text_document)?;
         Ok(Some(DocumentSymbolResponse::Nested(
             Self::nested_doc_symbols(encoding, document.symbols()),
➜  zuban git:(master) βœ—

AI generated report follows:

Document symbols return null for clients that don't set hierarchicalDocumentSymbolSupport

Summary

textDocument/documentSymbol returns result: null for any client whose
initialize capabilities don't set
textDocument.documentSymbol.hierarchicalDocumentSymbolSupport: true. Helix
sets it to false, so its document symbol picker is always empty.

Cause

document_symbols returns early with Ok(None) when the client doesn't
advertise hierarchical support:

Helix advertises hierarchicalDocumentSymbolSupport: false, but it accepts a
nested response and flattens it itself:

  • lsp.rs:374-386 β€” nested_to_flat flattens DocumentSymbolResponse::Nested
  • lsp.rs:356-359 β€” a null response is silently treated as "no symbols"

Environment

  • zuban 0.8.2
  • helix 25.07.1 (bbdb5094)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions