Return back Rust completion details (#22648)
Closes https://github.com/zed-industries/zed/issues/22642 In Zed, Rust's label generators expected the details to come in ` (use std.foo.Bar)` form, but recently, r-a started to send these details without the leading whitespace which broke the code generation. The PR makes LSP results parsing more lenient to work with both details' forms. Release Notes: - Fixed Rust completion labels not showing the imports
This commit is contained in:
parent
5f1eee3c66
commit
8151dc7696
1 changed files with 31 additions and 28 deletions
|
@ -253,49 +253,51 @@ impl LspAdapter for RustLspAdapter {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|detail| detail.detail.as_ref())
|
.and_then(|detail| detail.detail.as_ref())
|
||||||
.or(completion.detail.as_ref())
|
.or(completion.detail.as_ref())
|
||||||
.map(ToOwned::to_owned);
|
.map(|detail| detail.trim());
|
||||||
let function_signature = completion
|
let function_signature = completion
|
||||||
.label_details
|
.label_details
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|detail| detail.description.as_ref())
|
.and_then(|detail| detail.description.as_deref())
|
||||||
.or(completion.detail.as_ref())
|
.or(completion.detail.as_deref());
|
||||||
.map(ToOwned::to_owned);
|
match (detail, completion.kind) {
|
||||||
match completion.kind {
|
(Some(detail), Some(lsp::CompletionItemKind::FIELD)) => {
|
||||||
Some(lsp::CompletionItemKind::FIELD) if detail.is_some() => {
|
|
||||||
let name = &completion.label;
|
let name = &completion.label;
|
||||||
let text = format!("{}: {}", name, detail.unwrap());
|
let text = format!("{name}: {detail}");
|
||||||
let source = Rope::from(format!("struct S {{ {} }}", text).as_str());
|
let prefix = "struct S { ";
|
||||||
let runs = language.highlight_text(&source, 11..11 + text.len());
|
let source = Rope::from(format!("{prefix}{text} }}"));
|
||||||
|
let runs =
|
||||||
|
language.highlight_text(&source, prefix.len()..prefix.len() + text.len());
|
||||||
return Some(CodeLabel {
|
return Some(CodeLabel {
|
||||||
text,
|
text,
|
||||||
runs,
|
runs,
|
||||||
filter_range: 0..name.len(),
|
filter_range: 0..name.len(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Some(lsp::CompletionItemKind::CONSTANT | lsp::CompletionItemKind::VARIABLE)
|
(
|
||||||
if detail.is_some()
|
Some(detail),
|
||||||
&& completion.insert_text_format != Some(lsp::InsertTextFormat::SNIPPET) =>
|
Some(lsp::CompletionItemKind::CONSTANT | lsp::CompletionItemKind::VARIABLE),
|
||||||
{
|
) if completion.insert_text_format != Some(lsp::InsertTextFormat::SNIPPET) => {
|
||||||
let name = &completion.label;
|
let name = &completion.label;
|
||||||
let text = format!(
|
let text = format!(
|
||||||
"{}: {}",
|
"{}: {}",
|
||||||
name,
|
name,
|
||||||
completion.detail.as_ref().or(detail.as_ref()).unwrap()
|
completion.detail.as_deref().unwrap_or(detail)
|
||||||
);
|
);
|
||||||
let source = Rope::from(format!("let {} = ();", text).as_str());
|
let prefix = "let ";
|
||||||
let runs = language.highlight_text(&source, 4..4 + text.len());
|
let source = Rope::from(format!("{prefix}{text} = ();"));
|
||||||
|
let runs =
|
||||||
|
language.highlight_text(&source, prefix.len()..prefix.len() + text.len());
|
||||||
return Some(CodeLabel {
|
return Some(CodeLabel {
|
||||||
text,
|
text,
|
||||||
runs,
|
runs,
|
||||||
filter_range: 0..name.len(),
|
filter_range: 0..name.len(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Some(lsp::CompletionItemKind::FUNCTION | lsp::CompletionItemKind::METHOD)
|
(
|
||||||
if detail.is_some() =>
|
Some(detail),
|
||||||
{
|
Some(lsp::CompletionItemKind::FUNCTION | lsp::CompletionItemKind::METHOD),
|
||||||
|
) => {
|
||||||
static REGEX: LazyLock<Regex> = LazyLock::new(|| Regex::new("\\(…?\\)").unwrap());
|
static REGEX: LazyLock<Regex> = LazyLock::new(|| Regex::new("\\(…?\\)").unwrap());
|
||||||
|
|
||||||
let detail = detail.unwrap();
|
|
||||||
const FUNCTION_PREFIXES: [&str; 6] = [
|
const FUNCTION_PREFIXES: [&str; 6] = [
|
||||||
"async fn",
|
"async fn",
|
||||||
"async unsafe fn",
|
"async unsafe fn",
|
||||||
|
@ -315,10 +317,11 @@ impl LspAdapter for RustLspAdapter {
|
||||||
// fn keyword should be followed by opening parenthesis.
|
// fn keyword should be followed by opening parenthesis.
|
||||||
if let Some((prefix, suffix)) = fn_keyword {
|
if let Some((prefix, suffix)) = fn_keyword {
|
||||||
let mut text = REGEX.replace(&completion.label, suffix).to_string();
|
let mut text = REGEX.replace(&completion.label, suffix).to_string();
|
||||||
let source = Rope::from(format!("{prefix} {} {{}}", text).as_str());
|
let source = Rope::from(format!("{prefix} {text} {{}}"));
|
||||||
let run_start = prefix.len() + 1;
|
let run_start = prefix.len() + 1;
|
||||||
let runs = language.highlight_text(&source, run_start..run_start + text.len());
|
let runs = language.highlight_text(&source, run_start..run_start + text.len());
|
||||||
if detail.starts_with(" (") {
|
if detail.starts_with("(") {
|
||||||
|
text.push(' ');
|
||||||
text.push_str(&detail);
|
text.push_str(&detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,7 +345,7 @@ impl LspAdapter for RustLspAdapter {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(kind) => {
|
(_, Some(kind)) => {
|
||||||
let highlight_name = match kind {
|
let highlight_name = match kind {
|
||||||
lsp::CompletionItemKind::STRUCT
|
lsp::CompletionItemKind::STRUCT
|
||||||
| lsp::CompletionItemKind::INTERFACE
|
| lsp::CompletionItemKind::INTERFACE
|
||||||
|
@ -356,9 +359,9 @@ impl LspAdapter for RustLspAdapter {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut label = completion.label.clone();
|
let mut label = completion.label.clone();
|
||||||
if let Some(detail) = detail.filter(|detail| detail.starts_with(" (")) {
|
if let Some(detail) = detail.filter(|detail| detail.starts_with("(")) {
|
||||||
use std::fmt::Write;
|
label.push(' ');
|
||||||
write!(label, "{detail}").ok()?;
|
label.push_str(detail);
|
||||||
}
|
}
|
||||||
let mut label = CodeLabel::plain(label, None);
|
let mut label = CodeLabel::plain(label, None);
|
||||||
if let Some(highlight_name) = highlight_name {
|
if let Some(highlight_name) = highlight_name {
|
||||||
|
@ -883,7 +886,7 @@ mod tests {
|
||||||
kind: Some(lsp::CompletionItemKind::FUNCTION),
|
kind: Some(lsp::CompletionItemKind::FUNCTION),
|
||||||
label: "hello(…)".to_string(),
|
label: "hello(…)".to_string(),
|
||||||
label_details: Some(CompletionItemLabelDetails {
|
label_details: Some(CompletionItemLabelDetails {
|
||||||
detail: Some(" (use crate::foo)".into()),
|
detail: Some("(use crate::foo)".into()),
|
||||||
description: Some("fn(&mut Option<T>) -> Vec<T>".to_string())
|
description: Some("fn(&mut Option<T>) -> Vec<T>".to_string())
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue