rust_analyzer_cli/daemon/
state.rs1use 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}