rust-analyzer-cli 0.7.0

A library and CLI tool built on top of rust-analyzer for codebase navigation
Documentation
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(())
    }
}