Skip to content

feat: LSP (Language Server Protocol) integration v3 — clean rebuild#3219

Open
TheArchitectit wants to merge 1 commit into
ultraworkers:mainfrom
TheArchitectit:worktree-lsp-v3
Open

feat: LSP (Language Server Protocol) integration v3 — clean rebuild#3219
TheArchitectit wants to merge 1 commit into
ultraworkers:mainfrom
TheArchitectit:worktree-lsp-v3

Conversation

@TheArchitectit
Copy link
Copy Markdown
Contributor

Problem

All previous LSP PRs (#2813, #3016, #3098, #3099) were closed by the repo owner because they reverted upstream commits. The existing lsp_client.rs was a 747-line monolithic placeholder with no real language server communication -- the dispatch() method returned placeholder JSON instead of interacting with actual LSP servers.

Solution

Clean rebuild of the entire LSP integration layer from upstream/main, with zero upstream reverts. Replaced the placeholder with a fully functional, modular LSP subsystem split across four modules under 500 lines each.

Changes

New files

  • rust/crates/runtime/src/lsp_client/ (mod.rs, types.rs, dispatch.rs, tests.rs, tests_lifecycle.rs)

    • LspRegistry with Arc<Mutex>-based thread-safe server tracking
    • Lazy-start: servers auto-start on first dispatch() or file notification
    • register_with_descriptor() for deferred process launch
    • Full dispatch() routing for 12 LSP actions: diagnostics, hover, definition, references, completion, symbols, format, code_action, rename, signature_help, code_lens, workspace_symbols
    • didOpen/didChange/didClose file notifications with diagnostic caching
    • 58 unit tests covering registration, dispatch, lifecycle, edge cases
  • rust/crates/runtime/src/lsp_transport/ (mod.rs, tests.rs)

    • JSON-RPC 2.0 transport over stdin/stdout with Content-Length framing
    • TCP transport for GDScript/Godot LSP (port 6008) via socat/nc bridge
    • Request/response multiplexing with server-initiated notification queuing
    • Configurable request timeout (default 30s)
    • NODE_NO_WARNINGS=1 for Node.js-based servers
    • Graceful shutdown with kill fallback
  • rust/crates/runtime/src/lsp_process/ (mod.rs, parse.rs, tests.rs)

    • Full LSP lifecycle: initialize -> initialized -> requests -> shutdown
    • Comprehensive client capabilities declaration
    • All LSP features: hover, goto_definition, references, completion, document_symbols, formatting, didOpen/didChange/didClose, code_action, rename, signature_help, code_lens, workspace_symbols
    • Response parsing for all LSP result types
    • Diagnostic draining from publishDiagnostics notifications
  • rust/crates/runtime/src/lsp_discovery.rs

    • Auto-discovery of 14 known LSP servers via PATH probing
    • rustup proxy detection: falls back to rustup run stable rust-analyzer
    • Distro-aware install prompting (Debian, Fedora, Arch, openSUSE, Alpine, Void, NixOS, macOS, pip, npm)
    • GDScript/Godot TCP transport support

Modified files (LSP-only additions)

  • rust/crates/runtime/src/config.rs -- LspServerConfig struct, lspAutoStart config field (default true), lsp per-language config parsing, lsp()/lsp_auto_start() accessors
  • rust/crates/runtime/src/lib.rs -- pub mod lsp_discovery/lsp_process/lsp_transport declarations, LspServerConfig/LspServerDescriptor exports
  • rust/crates/commands/src/lib.rs -- /lsp slash command (action, target args)
  • rust/crates/tools/src/lib.rs -- LSP diagnostic enrichment in read/write/edit file operations, lsp_enrichment_for_path() and format_diagnostic_appendix() helpers, expanded LSP tool definition with code_action, rename, signature_help, code_lens, workspace_symbols actions
  • rust/crates/rusty-claude-cli/src/main.rs -- SlashCommand::Lsp match arms

Diff verification

17 files changed, 4705 insertions(+), 759 deletions(-)

The 759 deletions are entirely from the old monolithic lsp_client.rs which was replaced by the properly modularized lsp_client/ directory. All modifications to existing files are LSP-only additions. No upstream code was reverted. All 5 critical commits (b64df99, 91a0681, c345ce6, 85e736c, 5b79413) are preserved.

Testing

  1. cargo check --workspace -- compiles cleanly
  2. cargo test -p runtime -- 610 tests pass (58 LSP-specific, including transport, process, discovery, client, and dispatch tests)
  3. cargo test -p api -- 11 tests pass
  4. All LSP tests cover: registration, file extension mapping, diagnostic management, dispatch routing, status display, action aliases, server lifecycle, descriptor-based registration, error handling for missing/disconnected servers

Related PRs

Supersedes #2813, #3016, #3098, #3099 (all closed due to upstream reverts)

Adds a complete LSP integration layer built cleanly on top of upstream/main,
without reverting any upstream commits.

Problem: The previous LSP client was a 747-line monolithic placeholder file
(lsp_client.rs) with no real language server communication. The dispatch
method returned placeholder JSON instead of interacting with actual LSP
servers. There was no way to discover, start, stop, or query language
servers, and no auto-enrichment of diagnostics in tool output.

Solution: Replace the placeholder with a fully functional, modular LSP
subsystem split across four crates under 500 lines each:

lsp_client/ (mod.rs, types.rs, dispatch.rs, tests.rs, tests_lifecycle.rs):
  - LspRegistry with Arc<Mutex>-based thread-safe server tracking
  - Lazy-start: servers auto-start on first dispatch() or file notification
  - register_with_descriptor() for deferred process launch
  - Full dispatch() routing for 12 LSP actions: diagnostics, hover,
    definition, references, completion, symbols, format, code_action,
    rename, signature_help, code_lens, workspace_symbols
  - didOpen/didChange/didClose file notifications with diagnostic caching
  - 58 unit tests covering registration, dispatch, lifecycle, edge cases

lsp_transport/ (mod.rs, tests.rs):
  - JSON-RPC 2.0 transport over stdin/stdout with Content-Length framing
  - TCP transport for GDScript/Godot LSP (port 6008) via socat/nc bridge
  - Request/response multiplexing with server-initiated notification queuing
  - Configurable request timeout (default 30s)
  - NODE_NO_WARNINGS=1 for Node.js-based servers
  - Graceful shutdown with kill fallback

lsp_process/ (mod.rs, parse.rs, tests.rs):
  - Full LSP lifecycle: initialize -> initialized -> requests -> shutdown
  - Comprehensive client capabilities declaration
  - All LSP features: hover, goto_definition, references, completion,
    document_symbols, formatting, didOpen/didChange/didClose,
    code_action, rename, signature_help, code_lens, workspace_symbols
  - Response parsing for all LSP result types (MarkupContent, MarkedString,
    Location, DocumentSymbol, CompletionList, TextEdit, CodeAction,
    WorkspaceEdit, Rename, SignatureHelp, CodeLens)
  - Diagnostic draining from publishDiagnostics notifications

lsp_discovery.rs:
  - Auto-discovery of 14 known LSP servers via PATH probing
  - rustup proxy detection: falls back to 'rustup run stable rust-analyzer'
  - Distro-aware install prompting (Debian, Fedora, Arch, openSUSE, Alpine,
    Void, NixOS, macOS, pip, npm)
  - GDScript/Godot TCP transport support

Existing file modifications (LSP-only additions):
  - config.rs: LspServerConfig struct, lspAutoStart config field (default true),
    lsp per-language config parsing, lsp()/lsp_auto_start() accessors
  - lib.rs: pub mod lsp_discovery/lsp_process/lsp_transport declarations,
    LspServerConfig/LspServerDescriptor exports
  - commands/lib.rs: /lsp slash command (action, target args)
  - tools/lib.rs: LSP diagnostic enrichment in read/write/edit file operations,
    lsp_enrichment_for_path() and format_diagnostic_appendix() helpers,
    expanded LSP tool definition with code_action, rename, signature_help,
    code_lens, workspace_symbols actions
  - main.rs: SlashCommand::Lsp match arms (resume_supported, unimplemented)

This is a clean rebuild from upstream/main. All 5 critical commits
(b64df99, 91a0681, c345ce6, 85e736c, 5b79413) are preserved.
The diff is LSP-only additions; no upstream code was reverted.

Related: PRs ultraworkers#2813, ultraworkers#3016, ultraworkers#3098, ultraworkers#3099 (all closed due to upstream reverts)
@1716775457damn
Copy link
Copy Markdown

This is an impressive piece of work. The modular split across 4 crates (lsp_client, lsp_transport, lsp_process, lsp_discovery) with 58 unit tests is exactly the right architecture — much cleaner than the previous monolithic placeholder. The lazy-start pattern and diagnostic enrichment in tool output are the features that make this genuinely useful rather than just architectural.\n\nTwo things to check before merge:\n- build and cargo test are currently failing in CI — worth investigating if these are test assertions that need updating for the new LSP types\n- The auto-discovery of 14 LSP servers via PATH probing is great, but consider adding a claw lsp status command so users can confirm which servers were discovered and their health

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants