Add ruby LSP support via SolarGraph
This commit is contained in:
parent
e401caff7c
commit
36c07f940c
2 changed files with 156 additions and 2 deletions
145
crates/zed/src/languages/ruby.rs
Normal file
145
crates/zed/src/languages/ruby.rs
Normal file
|
@ -0,0 +1,145 @@
|
|||
use anyhow::{anyhow, Result};
|
||||
use async_trait::async_trait;
|
||||
use client::http::HttpClient;
|
||||
use language::{LanguageServerName, LspAdapter};
|
||||
use std::{any::Any, path::PathBuf, sync::Arc};
|
||||
|
||||
pub struct RubyLanguageServer;
|
||||
|
||||
#[async_trait]
|
||||
impl LspAdapter for RubyLanguageServer {
|
||||
async fn name(&self) -> LanguageServerName {
|
||||
LanguageServerName("solargraph".into())
|
||||
}
|
||||
|
||||
async fn server_args(&self) -> Vec<String> {
|
||||
vec!["stdio".into()]
|
||||
}
|
||||
|
||||
async fn fetch_latest_server_version(
|
||||
&self,
|
||||
_: Arc<dyn HttpClient>,
|
||||
) -> Result<Box<dyn 'static + Any + Send>> {
|
||||
Ok(Box::new(()))
|
||||
}
|
||||
|
||||
async fn fetch_server_binary(
|
||||
&self,
|
||||
_version: Box<dyn 'static + Send + Any>,
|
||||
_: Arc<dyn HttpClient>,
|
||||
_container_dir: PathBuf,
|
||||
) -> Result<PathBuf> {
|
||||
Err(anyhow!("solargraph must be installed manually"))
|
||||
}
|
||||
|
||||
async fn cached_server_binary(&self, _container_dir: PathBuf) -> Option<PathBuf> {
|
||||
Some("solargraph".into())
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue