Start work on syntax highlighting completions

This commit is contained in:
Max Brunsfeld 2022-02-02 18:14:30 -08:00
parent 45898daf83
commit 439d12cb85
7 changed files with 349 additions and 221 deletions

View file

@ -32,18 +32,36 @@ impl LspPostProcessor for RustPostProcessor {
}
}
fn label_for_completion(&self, completion: &lsp::CompletionItem) -> Option<String> {
fn label_for_completion(
&self,
completion: &lsp::CompletionItem,
language: &Language,
) -> Option<CompletionLabel> {
let detail = completion.detail.as_ref()?;
match completion.kind {
Some(
lsp::CompletionItemKind::CONSTANT
| lsp::CompletionItemKind::FIELD
| lsp::CompletionItemKind::VARIABLE,
) => {
let mut label = completion.label.clone();
label.push_str(": ");
label.push_str(detail);
Some(label)
Some(lsp::CompletionItemKind::FIELD) => {
let name = &completion.label;
let text = format!("{}: {}", name, detail);
let source = Rope::from(format!("struct S {{ {} }}", text).as_str());
let runs = language.highlight_text(&source, 11..11 + text.len());
return Some(CompletionLabel {
text,
runs,
filter_range: 0..name.len(),
left_aligned_len: name.len(),
});
}
Some(lsp::CompletionItemKind::CONSTANT | lsp::CompletionItemKind::VARIABLE) => {
let name = &completion.label;
let text = format!("{}: {}", name, detail);
let source = Rope::from(format!("let {} = ();", text).as_str());
let runs = language.highlight_text(&source, 4..4 + text.len());
return Some(CompletionLabel {
text,
runs,
filter_range: 0..name.len(),
left_aligned_len: name.len(),
});
}
Some(lsp::CompletionItemKind::FUNCTION | lsp::CompletionItemKind::METHOD) => {
lazy_static! {
@ -51,13 +69,20 @@ impl LspPostProcessor for RustPostProcessor {
}
if detail.starts_with("fn(") {
Some(REGEX.replace(&completion.label, &detail[2..]).to_string())
} else {
None
let text = REGEX.replace(&completion.label, &detail[2..]).to_string();
let source = Rope::from(format!("fn {} {{}}", text).as_str());
let runs = language.highlight_text(&source, 3..3 + text.len());
return Some(CompletionLabel {
left_aligned_len: text.find("->").unwrap_or(text.len()),
filter_range: 0..completion.label.find('(').unwrap_or(text.len()),
text,
runs,
});
}
}
_ => None,
_ => {}
}
None
}
}
@ -100,9 +125,10 @@ fn load_query(path: &str) -> Cow<'static, str> {
#[cfg(test)]
mod tests {
use super::*;
use gpui::color::Color;
use language::LspPostProcessor;
use super::RustPostProcessor;
use theme::SyntaxTheme;
#[test]
fn test_process_rust_diagnostics() {
@ -144,4 +170,82 @@ mod tests {
"cannot borrow `self.d` as mutable\n`self` is a `&` reference"
);
}
#[test]
fn test_process_rust_completions() {
let language = rust();
let grammar = language.grammar().unwrap();
let theme = SyntaxTheme::new(vec![
("type".into(), Color::green().into()),
("keyword".into(), Color::blue().into()),
("function".into(), Color::red().into()),
("property".into(), Color::white().into()),
]);
language.set_theme(&theme);
let highlight_function = grammar.highlight_id_for_name("function").unwrap();
let highlight_type = grammar.highlight_id_for_name("type").unwrap();
let highlight_keyword = grammar.highlight_id_for_name("keyword").unwrap();
let highlight_field = grammar.highlight_id_for_name("property").unwrap();
assert_eq!(
language.label_for_completion(&lsp::CompletionItem {
kind: Some(lsp::CompletionItemKind::FUNCTION),
label: "hello(…)".to_string(),
detail: Some("fn(&mut Option<T>) -> Vec<T>".to_string()),
..Default::default()
}),
Some(CompletionLabel {
text: "hello(&mut Option<T>) -> Vec<T>".to_string(),
filter_range: 0..5,
runs: vec![
(0..5, highlight_function),
(7..10, highlight_keyword),
(11..17, highlight_type),
(18..19, highlight_type),
(25..28, highlight_type),
(29..30, highlight_type),
],
left_aligned_len: 22,
})
);
assert_eq!(
language.label_for_completion(&lsp::CompletionItem {
kind: Some(lsp::CompletionItemKind::FIELD),
label: "len".to_string(),
detail: Some("usize".to_string()),
..Default::default()
}),
Some(CompletionLabel {
text: "len: usize".to_string(),
filter_range: 0..3,
runs: vec![(0..3, highlight_field), (5..10, highlight_type),],
left_aligned_len: 3,
})
);
assert_eq!(
language.label_for_completion(&lsp::CompletionItem {
kind: Some(lsp::CompletionItemKind::FUNCTION),
label: "hello(…)".to_string(),
detail: Some("fn(&mut Option<T>) -> Vec<T>".to_string()),
..Default::default()
}),
Some(CompletionLabel {
text: "hello(&mut Option<T>) -> Vec<T>".to_string(),
filter_range: 0..5,
runs: vec![
(0..5, highlight_function),
(7..10, highlight_keyword),
(11..17, highlight_type),
(18..19, highlight_type),
(25..28, highlight_type),
(29..30, highlight_type),
],
left_aligned_len: 22,
})
);
}
}