use crate::lsp::client::LspClient;
use std::path::PathBuf;
use std::sync::Arc;
use tokio::sync::RwLock;
pub struct AppState {
pub workspace_root: PathBuf,
pub lsp_client: Arc<RwLock<Option<Arc<LspClient>>>>,
pub last_error: Arc<RwLock<Option<String>>>,
}
impl AppState {
pub fn new(workspace_root: PathBuf) -> Self {
let canonical_root = workspace_root
.canonicalize()
.unwrap_or_else(|_| workspace_root.clone());
Self {
workspace_root: canonical_root,
lsp_client: Arc::new(RwLock::new(None)),
last_error: Arc::new(RwLock::new(None)),
}
}
pub async fn get_or_start_lsp(&self) -> anyhow::Result<Arc<LspClient>> {
{
let lock = self.lsp_client.read().await;
if let Some(client) = lock.as_ref() {
return Ok(client.clone());
}
}
let mut lock = self.lsp_client.write().await;
if let Some(client) = lock.as_ref() {
return Ok(client.clone());
}
let client = match LspClient::start(&self.workspace_root).await {
Ok(client) => Arc::new(client),
Err(error) => {
*self.last_error.write().await = Some(error.to_string());
return Err(error);
}
};
*self.last_error.write().await = None;
*lock = Some(client.clone());
Ok(client)
}
pub async fn refresh_lsp(&self) -> anyhow::Result<()> {
let old_client = {
let mut lock = self.lsp_client.write().await;
lock.take()
};
if let Some(client) = old_client {
client.shutdown().await;
}
let client = match LspClient::start(&self.workspace_root).await {
Ok(client) => Arc::new(client),
Err(error) => {
*self.last_error.write().await = Some(error.to_string());
return Err(error);
}
};
*self.last_error.write().await = None;
*self.lsp_client.write().await = Some(client);
Ok(())
}
}