lspz 0.10.3

AI-friendly LSP compression proxy
Documentation
use std::collections::HashMap;

use super::session::{InitializeParams, LspSession};

/// A pool of LSP sessions, keyed by `(language, workspace_root)`.
///
/// Sessions are created lazily on first access. Different workspace roots
/// get separate sessions so each LSP server analyzes the correct project.
pub struct LspPool {
    sessions: HashMap<String, LspSession>,
}

impl LspPool {
    /// Create an empty pool.
    pub fn new() -> Self {
        Self {
            sessions: HashMap::new(),
        }
    }

    /// Get or create a session for the given language and workspace root.
    ///
    /// `root_path` is a canonicalized absolute path (no `file://` prefix) used
    /// both as part of the cache key and as the LSP `rootUri` during initialization.
    pub async fn get_or_spawn(
        &mut self,
        language: &str,
        cmd: &str,
        root_path: Option<&str>,
    ) -> Result<&mut LspSession, anyhow::Error> {
        let key = match root_path {
            Some(root) => format!("{language}:{root}"),
            None => language.to_string(),
        };
        if !self.sessions.contains_key(&key) {
            let mut session = LspSession::spawn(cmd)?;
            let init_params = InitializeParams {
                root_uri: root_path.map(|s| s.to_string()),
            };
            session.initialize(init_params).await?;
            tracing::info!(key, "LSP session initialized");
            self.sessions.insert(key.clone(), session);
        }
        Ok(self.sessions.get_mut(&key).unwrap())
    }
}

impl Default for LspPool {
    fn default() -> Self {
        Self::new()
    }
}