Crate lsp_bridge

Source
Expand description

§LSP Bridge

A comprehensive Rust library that provides a bridge between Language Server Protocol (LSP) servers and clients. It simplifies the integration of LSP capabilities into applications, tools, and IDEs by handling the complexity of protocol communication, lifecycle management, and feature negotiation.

§Architecture

┌─────────────────────────────────────────────────────────────┐
│                    Your Application                         │
└─────────────────────┬───────────────────────────────────────┘
                      │
┌─────────────────────▼───────────────────────────────────────┐
│                   LspBridge                                 │
│  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐          │
│  │   Config    │ │   Monitor   │ │   Registry  │          │
│  │   Manager   │ │   Health    │ │   Servers   │          │
│  └─────────────┘ └─────────────┘ └─────────────┘          │
└─────────────────────┬───────────────────────────────────────┘
                      │
┌─────────────────────▼───────────────────────────────────────┐
│                   LspClient                                 │
│  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐          │
│  │   Message   │ │   Server    │ │   Active    │          │
│  │   Router    │ │   Pool      │ │   Tracker   │          │
│  └─────────────┘ └─────────────┘ └─────────────┘          │
└─────────────────────┬───────────────────────────────────────┘
                      │
┌─────────────────────▼───────────────────────────────────────┐
│                   LspServer                                 │
│  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐          │
│  │   State     │ │   Request   │ │   Process   │          │
│  │   Manager   │ │   Handler   │ │   Manager   │          │
│  └─────────────┘ └─────────────┘ └─────────────┘          │
└─────────────────────┬───────────────────────────────────────┘
                      │
┌─────────────────────▼───────────────────────────────────────┐
│              External LSP Servers                           │
│  ┌─────────────┐ ┌─────────────┐ ┌─────────────┐          │
│  │rust-analyzer│ │typescript-ls│ │    pylsp    │    ...   │
│  └─────────────┘ └─────────────┘ └─────────────┘          │
└─────────────────────────────────────────────────────────────┘

§Features

  • Complete LSP protocol implementation (version 3.17+)
  • Server lifecycle management (startup, shutdown, crash recovery)
  • Asynchronous communication handling with tokio
  • Automatic server capability detection and negotiation
  • Request/notification routing and multiplexing
  • Support for custom LSP extensions
  • Language-specific configuration
  • Progress reporting and cancellation
  • Document synchronization
  • Multi-server coordination
  • Built-in monitoring and observability
  • Thread-safe concurrent operations

§Quick Start

§Basic Setup

use lsp_bridge::{LspBridge, LspServerConfig};
use std::path::PathBuf;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create a new bridge
    let mut bridge = LspBridge::new();
     
    // Configure rust-analyzer server
    let config = LspServerConfig::new()
        .command("rust-analyzer")
        .root_path(PathBuf::from("/path/to/project"));
     
    // Register and start the server
    let server_id = bridge.register_server("rust-analyzer", config).await?;
    bridge.start_server(&server_id).await?;
     
    // Open a document
    bridge.open_document(
        &server_id,
        "file:///path/to/file.rs",
        &std::fs::read_to_string("/path/to/file.rs")?
    ).await?;
     
    // Get completions
    let completions = bridge.get_completions(
        &server_id,
        "file:///path/to/file.rs",
        lsp_types::Position::new(10, 5)
    ).await?;
     
    println!("Found {} completions", completions.len());
     
    // Clean shutdown
    bridge.stop_server(&server_id).await?;
    Ok(())
}

§Multi-Server Setup

use lsp_bridge::{LspBridge, LspServerConfig};
use std::path::PathBuf;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut bridge = LspBridge::new();
     
    // Configure multiple servers
    let workspace = PathBuf::from("/path/to/mixed/project");
     
    // Rust server
    let rust_config = LspServerConfig::new()
        .command("rust-analyzer")
        .root_path(workspace.clone());
    let rust_id = bridge.register_server("rust", rust_config).await?;
     
    // TypeScript server  
    let ts_config = LspServerConfig::new()
        .command("typescript-language-server")
        .args(vec!["--stdio".to_string()])
        .root_path(workspace.clone());
    let ts_id = bridge.register_server("typescript", ts_config).await?;
     
    // Start both servers
    bridge.start_server(&rust_id).await?;
    bridge.start_server(&ts_id).await?;
     
    // Work with different file types
    bridge.open_document(&rust_id, "file:///project/src/main.rs", "fn main() {}").await?;
    bridge.open_document(&ts_id, "file:///project/index.ts", "console.log('hi')").await?;
     
    // Get language-specific features
    let rust_hover = bridge.get_hover(&rust_id, "file:///project/src/main.rs", 
                                      lsp_types::Position::new(0, 3)).await?;
    let ts_completions = bridge.get_completions(&ts_id, "file:///project/index.ts",
                                                 lsp_types::Position::new(0, 8)).await?;
     
    Ok(())
}

§Architecture

The LSP Bridge is structured around several core components:

  • LspBridge: Main coordination interface managing multiple servers
  • LspClient: Client-side protocol implementation
  • LspServer: Individual server lifecycle and communication
  • LspServerConfig: Server configuration and validation
  • Protocol types: Type-safe LSP message handling

§Error Handling

All operations return Result<T, LspBridgeError> which provides detailed error context and recovery information:

use lsp_bridge::{LspBridge, error::LspBridgeError};

async fn handle_errors() {
    let mut bridge = LspBridge::new();
     
    match bridge.start_server("non-existent").await {
        Ok(_) => println!("Server started"),
        Err(LspBridgeError::Lsp(err)) => {
            println!("LSP error: {}", err);
            // Handle LSP-specific errors
        },
        Err(LspBridgeError::Io(err)) => {
            println!("I/O error: {}", err);
            // Handle I/O errors  
        },
        Err(err) => {
            println!("Other error: {}", err);
        }
    }
}

§Thread Safety

All operations are thread-safe and can be used from multiple async tasks:

use lsp_bridge::LspBridge;
use std::sync::Arc;
use tokio::task;

async fn concurrent_operations() {
    let bridge = Arc::new(LspBridge::new());
     
    let bridge1 = bridge.clone();
    let bridge2 = bridge.clone();
     
    let task1 = task::spawn(async move {
        // Work with bridge1
    });
     
    let task2 = task::spawn(async move {
        // Work with bridge2  
    });
     
    let _ = tokio::try_join!(task1, task2);
}

§Example Usage

use lsp_bridge::{LspBridge, LspServerConfig};
use std::path::PathBuf;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Configure the LSP server
    let config = LspServerConfig::new()
        .command("rust-analyzer")
        .root_path(PathBuf::from("/path/to/project"));
     
    // Create and start the bridge
    let mut bridge = LspBridge::new();
    let server_id = bridge.register_server("rust", config).await?;
    bridge.start_server(&server_id).await?;
     
    // Use LSP features
    let document_uri = "file:///path/to/project/src/main.rs";
    bridge.open_document(&server_id, document_uri, "fn main() {}").await?;
     
    Ok(())
}

§Performance

The LSP Bridge is designed for high performance with:

  • Async/await throughout for non-blocking operations
  • Efficient message serialization (~370ns for typical messages)
  • Memory-efficient data structures with DashMap
  • Connection pooling and resource management

§License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.

Re-exports§

pub use bridge::LspBridge;
pub use client::LspClient;
pub use config::LspClientCapabilities;
pub use config::LspServerConfig;
pub use error::LspBridgeError;
pub use error::LspError;
pub use error::Result;
pub use hardening::HardeningConfig;
pub use hardening::HardeningManager;
pub use hardening::ResourceLimits;
pub use monitoring::HealthStatus;
pub use monitoring::MetricsCollector;
pub use monitoring::MetricsSnapshot;
pub use protocol::LspMessage;
pub use protocol::LspNotification;
pub use protocol::LspRequest;
pub use protocol::LspResponse;
pub use server::LspServer;
pub use server::LspServerManager;

Modules§

bridge
Main LSP Bridge interface coordinating client-server communication.
client
Client-side bridge implementation for LSP interactions.
config
Configuration types and builders for LSP Bridge.
error
Error types and utilities for LSP Bridge.
hardening
Production hardening and resource limits
monitoring
Production monitoring and metrics collection
prelude
Prelude module for common imports
process
LSP server process management and communication.
protocol
LSP protocol implementation and utilities.
server
LSP server lifecycle management and communication.
utils
Utility functions and helpers for LSP Bridge.