Skip to main content

rust_analyzer_cli/daemon/
state.rs

1use crate::lsp::client::LspClient;
2use std::path::PathBuf;
3use std::sync::Arc;
4use tokio::sync::RwLock;
5
6pub struct AppState {
7    pub workspace_root: PathBuf,
8    pub lsp_client: Arc<RwLock<Option<Arc<LspClient>>>>,
9    pub last_error: Arc<RwLock<Option<String>>>,
10}
11
12impl AppState {
13    pub fn new(workspace_root: PathBuf) -> Self {
14        let canonical_root = workspace_root
15            .canonicalize()
16            .unwrap_or_else(|_| workspace_root.clone());
17        Self {
18            workspace_root: canonical_root,
19            lsp_client: Arc::new(RwLock::new(None)),
20            last_error: Arc::new(RwLock::new(None)),
21        }
22    }
23
24    pub async fn get_or_start_lsp(&self) -> anyhow::Result<Arc<LspClient>> {
25        {
26            let lock = self.lsp_client.read().await;
27            if let Some(client) = lock.as_ref() {
28                return Ok(client.clone());
29            }
30        }
31
32        let mut lock = self.lsp_client.write().await;
33        if let Some(client) = lock.as_ref() {
34            return Ok(client.clone());
35        }
36
37        let client = match LspClient::start(&self.workspace_root).await {
38            Ok(client) => Arc::new(client),
39            Err(error) => {
40                *self.last_error.write().await = Some(error.to_string());
41                return Err(error);
42            }
43        };
44        *self.last_error.write().await = None;
45        *lock = Some(client.clone());
46        Ok(client)
47    }
48
49    pub async fn refresh_lsp(&self) -> anyhow::Result<()> {
50        let old_client = {
51            let mut lock = self.lsp_client.write().await;
52            lock.take()
53        };
54        if let Some(client) = old_client {
55            client.shutdown().await;
56        }
57
58        let client = match LspClient::start(&self.workspace_root).await {
59            Ok(client) => Arc::new(client),
60            Err(error) => {
61                *self.last_error.write().await = Some(error.to_string());
62                return Err(error);
63            }
64        };
65        *self.last_error.write().await = None;
66        *self.lsp_client.write().await = Some(client);
67        Ok(())
68    }
69}