157 lines · 5.1 KB · Rust
RawDownload
use anyhow::{anyhow, Result};use async_trait::async_trait;use language::{LanguageServerName, LspAdapter, LspAdapterDelegate};use lsp::LanguageServerBinary;use std::{any::Any, path::PathBuf, sync::Arc}; pub struct RubyLanguageServer; #[async_trait(?Send)]impl LspAdapter for RubyLanguageServer {    fn name(&self) -> LanguageServerName {        LanguageServerName("solargraph".into())    }     async fn fetch_latest_server_version(        &self,        _: &dyn LspAdapterDelegate,    ) -> Result<Box<dyn 'static + Any + Send>> {        Ok(Box::new(()))    }     async fn fetch_server_binary(        &self,        _version: Box<dyn 'static + Send + Any>,        _container_dir: PathBuf,        _: &dyn LspAdapterDelegate,    ) -> Result<LanguageServerBinary> {        Err(anyhow!("solargraph must be installed manually"))    }     async fn cached_server_binary(        &self,        _: PathBuf,        _: &dyn LspAdapterDelegate,    ) -> Option<LanguageServerBinary> {        Some(LanguageServerBinary {            path: "solargraph".into(),            env: None,            arguments: vec!["stdio".into()],        })    }     fn can_be_reinstalled(&self) -> bool {        false    }     async fn installation_test_binary(&self, _: PathBuf) -> Option<LanguageServerBinary> {        None    }     async fn label_for_completion(        &self,        item: &lsp::CompletionItem,        language: &Arc<language::Language>,    ) -> Option<language::CodeLabel> {        let label = &item.label;        let grammar = language.grammar()?;        let highlight_id = match item.kind? {            lsp::CompletionItemKind::METHOD => grammar.highlight_id_for_name("function.method")?,            lsp::CompletionItemKind::CONSTANT => grammar.highlight_id_for_name("constant")?,            lsp::CompletionItemKind::CLASS | lsp::CompletionItemKind::MODULE => {                grammar.highlight_id_for_name("type")?            }            lsp::CompletionItemKind::KEYWORD => {                if label.starts_with(':') {                    grammar.highlight_id_for_name("string.special.symbol")?                } else {                    grammar.highlight_id_for_name("keyword")?                }            }            lsp::CompletionItemKind::VARIABLE => {                if label.starts_with('@') {                    grammar.highlight_id_for_name("property")?                } else {                    return None;                }            }            _ => return None,        };        Some(language::CodeLabel {            text: label.clone(),            runs: vec![(0..label.len(), highlight_id)],            filter_range: 0..label.len(),        })    }     async fn label_for_symbol(        &self,        label: &str,        kind: lsp::SymbolKind,        language: &Arc<language::Language>,    ) -> Option<language::CodeLabel> {        let grammar = language.grammar()?;        match kind {            lsp::SymbolKind::METHOD => {                let mut parts = label.split('#');                let classes = parts.next()?;                let method = parts.next()?;                if parts.next().is_some() {                    return None;                }                 let class_id = grammar.highlight_id_for_name("type")?;                let method_id = grammar.highlight_id_for_name("function.method")?;                 let mut ix = 0;                let mut runs = Vec::new();                for (i, class) in classes.split("::").enumerate() {                    if i > 0 {                        ix += 2;                    }                    let end_ix = ix + class.len();                    runs.push((ix..end_ix, class_id));                    ix = end_ix;                }                 ix += 1;                let end_ix = ix + method.len();                runs.push((ix..end_ix, method_id));                Some(language::CodeLabel {                    text: label.to_string(),                    runs,                    filter_range: 0..label.len(),                })            }            lsp::SymbolKind::CONSTANT => {                let constant_id = grammar.highlight_id_for_name("constant")?;                Some(language::CodeLabel {                    text: label.to_string(),                    runs: vec![(0..label.len(), constant_id)],                    filter_range: 0..label.len(),                })            }            lsp::SymbolKind::CLASS | lsp::SymbolKind::MODULE => {                let class_id = grammar.highlight_id_for_name("type")?;                 let mut ix = 0;                let mut runs = Vec::new();                for (i, class) in label.split("::").enumerate() {                    if i > 0 {                        ix += "::".len();                    }                    let end_ix = ix + class.len();                    runs.push((ix..end_ix, class_id));                    ix = end_ix;                }                 Some(language::CodeLabel {                    text: label.to_string(),                    runs,                    filter_range: 0..label.len(),                })            }            _ => return None,        }    }}