elixir: Improve ElixirLS LSP autocomplete to show labelDetails information (#21666)

Closes https://github.com/zed-industries/zed/issues/19688

Release Notes:

- Improved ElixirLS LSP autocomplete to show module, function and struct
field details

![image](https://github.com/user-attachments/assets/2f05183f-8f7f-42c3-ba14-28fc58522488)

![image](https://github.com/user-attachments/assets/bfdea373-79ec-4dec-a9c7-5d15ad9403ee)

![image](https://github.com/user-attachments/assets/c0fd66d5-0e01-4e1e-a2d5-0a78d38e0b72)
This commit is contained in:
João Otávio Biondo 2024-12-12 21:16:23 -03:00 committed by GitHub
parent 6a37307302
commit 74d7ce2d2b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 75 additions and 15 deletions

View file

@ -13,4 +13,4 @@ path = "src/elixir.rs"
crate-type = ["cdylib"]
[dependencies]
zed_extension_api = "0.1.0"
zed_extension_api = "0.2.0"

View file

@ -107,36 +107,85 @@ impl ElixirLs {
}
pub fn label_for_completion(&self, completion: Completion) -> Option<CodeLabel> {
let name = &completion.label;
let detail = completion
.detail
.filter(|detail| detail != "alias")
.map(|detail| format!(": {detail}"))
.unwrap_or("".to_string());
let detail_span = CodeLabelSpan::literal(detail, Some("comment.unused".to_string()));
match completion.kind? {
CompletionKind::Module
| CompletionKind::Class
| CompletionKind::Interface
| CompletionKind::Struct => {
let name = completion.label;
CompletionKind::Module | CompletionKind::Class | CompletionKind::Struct => {
let defmodule = "defmodule ";
let code = format!("{defmodule}{name}");
let alias = completion
.label_details
.and_then(|details| details.description)
.filter(|description| description.starts_with("alias"))
.map(|description| format!(" ({description})"))
.unwrap_or("".to_string());
let code = format!("{defmodule}{name}{alias}");
let name_start = defmodule.len();
let name_end = name_start + name.len();
Some(CodeLabel {
code,
spans: vec![CodeLabelSpan::code_range(
defmodule.len()..defmodule.len() + name.len(),
)],
spans: vec![
CodeLabelSpan::code_range(name_start..name_end),
detail_span,
CodeLabelSpan::code_range(name_end..(name_end + alias.len())),
],
filter_range: (0..name.len()).into(),
})
}
CompletionKind::Interface => Some(CodeLabel {
code: name.to_string(),
spans: vec![CodeLabelSpan::code_range(0..name.len()), detail_span],
filter_range: (0..name.len()).into(),
}),
CompletionKind::Field => Some(CodeLabel {
code: name.to_string(),
spans: vec![
CodeLabelSpan::literal(name, Some("function".to_string())),
detail_span,
],
filter_range: (0..name.len()).into(),
}),
CompletionKind::Function | CompletionKind::Constant => {
let name = completion.label;
let detail = completion
.label_details
.clone()
.and_then(|details| details.detail)
.unwrap_or("".to_string());
let description = completion
.label_details
.clone()
.and_then(|details| details.description)
.map(|description| format!(" ({description})"))
.unwrap_or("".to_string());
let def = "def ";
let code = format!("{def}{name}");
let code = format!("{def}{name}{detail}{description}");
let name_start = def.len();
let name_end = name_start + name.len();
let detail_end = name_end + detail.len();
let description_end = detail_end + description.len();
Some(CodeLabel {
code,
spans: vec![CodeLabelSpan::code_range(def.len()..def.len() + name.len())],
spans: vec![
CodeLabelSpan::code_range(name_start..name_end),
CodeLabelSpan::code_range(name_end..detail_end),
CodeLabelSpan::code_range(detail_end..description_end),
],
filter_range: (0..name.len()).into(),
})
}
CompletionKind::Operator => {
let name = completion.label;
let def_a = "def a ";
let code = format!("{def_a}{name} b");