use std::collections::HashMap;
use super::session::{InitializeParams, LspSession};
pub struct LspPool {
sessions: HashMap<String, LspSession>,
}
impl LspPool {
pub fn new() -> Self {
Self {
sessions: HashMap::new(),
}
}
pub async fn get_or_spawn(
&mut self,
language: &str,
cmd: &str,
root_path: Option<&str>,
extra_args: &[String],
) -> Result<&mut LspSession, anyhow::Error> {
let key = pool_key(language, cmd, root_path);
if !self.sessions.contains_key(&key) {
let mut session = LspSession::spawn_with_args(cmd, extra_args)?;
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())
}
pub fn get_mut_by_key(&mut self, key: &str) -> Result<&mut LspSession, anyhow::Error> {
self.sessions
.get_mut(key)
.ok_or_else(|| anyhow::anyhow!("no session for key: {key}"))
}
pub fn contains_key(&self, key: &str) -> bool {
self.sessions.contains_key(key)
}
pub fn session_keys(&self) -> Vec<String> {
self.sessions.keys().cloned().collect()
}
}
#[cfg(test)]
impl LspPool {
pub fn insert_session_for_test(&mut self, key: &str, session: LspSession) {
self.sessions.insert(key.to_string(), session);
}
}
impl Default for LspPool {
fn default() -> Self {
Self::new()
}
}
pub fn pool_key(language: &str, cmd: &str, root_path: Option<&str>) -> String {
match root_path {
Some(root) => format!("{language}:{cmd}:{root}"),
None => format!("{language}:{cmd}"),
}
}