ZIm/extensions/ruby/src/language_servers/solargraph.rs
Vitaly Slobodin 43be375c76
ruby: Fix solargraph completion highlighting (#11825)
Hi. This pull request fixes a small error with `solargraph` completions
to make them more detailed. It removes the nested match expression to
resolve the problem with highlighting the completion items and their
signatures with the return type as well. Thanks.

See screenshots below.

Release Notes:

- N/A

| Before  | After |
| ------------- | ------------- |
| ![CleanShot 2024-05-14 at 23 23
00@2x](https://github.com/zed-industries/zed/assets/1894248/4ea1fa41-1189-4607-8aea-547c27229a18)
| ![CleanShot 2024-05-14 at 23 29
30@2x](https://github.com/zed-industries/zed/assets/1894248/3c7be39a-2c7b-4662-8519-8c258c049cfa)
|
2024-05-14 18:54:19 -04:00

115 lines
3.8 KiB
Rust

use zed::lsp::{Completion, CompletionKind, Symbol, SymbolKind};
use zed::{CodeLabel, CodeLabelSpan};
use zed_extension_api::{self as zed, Result};
pub struct Solargraph {}
impl Solargraph {
pub const LANGUAGE_SERVER_ID: &'static str = "solargraph";
pub fn new() -> Self {
Self {}
}
pub fn server_script_path(&mut self, worktree: &zed::Worktree) -> Result<String> {
let path = worktree
.which("solargraph")
.ok_or_else(|| "solargraph must be installed manually".to_string())?;
Ok(path)
}
pub fn label_for_completion(&self, completion: Completion) -> Option<CodeLabel> {
let highlight_name = match completion.kind? {
CompletionKind::Class | CompletionKind::Module => "type",
CompletionKind::Constant => "constant",
CompletionKind::Method => "function.method",
CompletionKind::Keyword => {
if completion.label.starts_with(':') {
"string.special.symbol"
} else {
"keyword"
}
}
CompletionKind::Variable => {
if completion.label.starts_with('@') {
"property"
} else {
return None;
}
}
_ => return None,
};
let len = completion.label.len();
let name_span = CodeLabelSpan::literal(completion.label, Some(highlight_name.to_string()));
Some(CodeLabel {
code: Default::default(),
spans: if let Some(detail) = completion.detail {
vec![
name_span,
CodeLabelSpan::literal(" ", None),
CodeLabelSpan::literal(detail, None),
]
} else {
vec![name_span]
},
filter_range: (0..len).into(),
})
}
pub fn label_for_symbol(&self, symbol: Symbol) -> Option<CodeLabel> {
let name = &symbol.name;
return match symbol.kind {
SymbolKind::Method => {
let mut parts = name.split('#');
let container_name = parts.next()?;
let method_name = parts.next()?;
if parts.next().is_some() {
return None;
}
let filter_range = 0..name.len();
let spans = vec![
CodeLabelSpan::literal(container_name, Some("type".to_string())),
CodeLabelSpan::literal("#", None),
CodeLabelSpan::literal(method_name, Some("function.method".to_string())),
];
Some(CodeLabel {
code: name.to_string(),
spans,
filter_range: filter_range.into(),
})
}
SymbolKind::Class | SymbolKind::Module => {
let class = "class ";
let code = format!("{class}{name}");
let filter_range = 0..name.len();
let display_range = class.len()..class.len() + name.len();
Some(CodeLabel {
code,
spans: vec![CodeLabelSpan::code_range(display_range)],
filter_range: filter_range.into(),
})
}
SymbolKind::Constant => {
let code = name.to_uppercase().to_string();
let filter_range = 0..name.len();
let display_range = 0..name.len();
Some(CodeLabel {
code,
spans: vec![CodeLabelSpan::code_range(display_range)],
filter_range: filter_range.into(),
})
}
_ => None,
};
}
}