Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-completion/src/item.rs')
| -rw-r--r-- | crates/ide-completion/src/item.rs | 56 |
1 files changed, 36 insertions, 20 deletions
diff --git a/crates/ide-completion/src/item.rs b/crates/ide-completion/src/item.rs index 8878fbbea3..9608eed99d 100644 --- a/crates/ide-completion/src/item.rs +++ b/crates/ide-completion/src/item.rs @@ -10,7 +10,7 @@ use ide_db::{ }; use itertools::Itertools; use smallvec::SmallVec; -use stdx::{impl_from, never}; +use stdx::{format_to, impl_from, never}; use syntax::{format_smolstr, Edition, SmolStr, TextRange, TextSize}; use crate::{ @@ -27,10 +27,7 @@ use crate::{ #[non_exhaustive] pub struct CompletionItem { /// Label in the completion pop up which identifies completion. - pub label: SmolStr, - /// Additional label details in the completion pop up that are - /// displayed and aligned on the right side after the label. - pub label_detail: Option<SmolStr>, + pub label: CompletionItemLabel, /// Range of identifier that is being completed. /// @@ -89,11 +86,23 @@ pub struct CompletionItem { pub import_to_add: SmallVec<[(String, String); 1]>, } +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct CompletionItemLabel { + /// The primary label for the completion item. + pub primary: SmolStr, + /// The left detail for the completion item, usually rendered right next to the primary label. + pub detail_left: Option<String>, + /// The right detail for the completion item, usually rendered right aligned at the end of the completion item. + pub detail_right: Option<String>, +} // We use custom debug for CompletionItem to make snapshot tests more readable. impl fmt::Debug for CompletionItem { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut s = f.debug_struct("CompletionItem"); - s.field("label", &self.label).field("source_range", &self.source_range); + s.field("label", &self.label.primary) + .field("detail_left", &self.label.detail_left) + .field("detail_right", &self.label.detail_right) + .field("source_range", &self.source_range); if self.text_edit.len() == 1 { let atom = self.text_edit.iter().next().unwrap(); s.field("delete", &atom.delete); @@ -102,7 +111,7 @@ impl fmt::Debug for CompletionItem { s.field("text_edit", &self.text_edit); } s.field("kind", &self.kind); - if self.lookup() != self.label { + if self.lookup() != self.label.primary { s.field("lookup", &self.lookup()); } if let Some(detail) = &self.detail { @@ -434,7 +443,7 @@ impl CompletionItem { self.ref_match.map(|(mutability, offset)| { ( - format!("&{}{}", mutability.as_keyword_for_ref(), self.label), + format!("&{}{}", mutability.as_keyword_for_ref(), self.label.primary), ide_db::text_edit::Indel::insert( offset, format!("&{}", mutability.as_keyword_for_ref()), @@ -488,13 +497,13 @@ impl Builder { let _p = tracing::info_span!("item::Builder::build").entered(); let label = self.label; - let mut label_detail = None; let mut lookup = self.lookup.unwrap_or_else(|| label.clone()); let insert_text = self.insert_text.unwrap_or_else(|| label.to_string()); + let mut detail_left = None; if !self.doc_aliases.is_empty() { let doc_aliases = self.doc_aliases.iter().join(", "); - label_detail.replace(format_smolstr!(" (alias {doc_aliases})")); + detail_left = Some(format!("(alias {doc_aliases})")); let lookup_doc_aliases = self .doc_aliases .iter() @@ -516,16 +525,20 @@ impl Builder { } if let [import_edit] = &*self.imports_to_add { // snippets can have multiple imports, but normal completions only have up to one - label_detail.replace(format_smolstr!( - "{} (use {})", - label_detail.as_deref().unwrap_or_default(), + let detail_left = detail_left.get_or_insert_with(String::new); + format_to!( + detail_left, + "{}(use {})", + if detail_left.is_empty() { "" } else { " " }, import_edit.import_path.display(db, self.edition) - )); + ); } else if let Some(trait_name) = self.trait_name { - label_detail.replace(format_smolstr!( - "{} (as {trait_name})", - label_detail.as_deref().unwrap_or_default(), - )); + let detail_left = detail_left.get_or_insert_with(String::new); + format_to!( + detail_left, + "{}(as {trait_name})", + if detail_left.is_empty() { "" } else { " " }, + ); } let text_edit = match self.text_edit { @@ -546,8 +559,11 @@ impl Builder { CompletionItem { source_range: self.source_range, - label, - label_detail, + label: CompletionItemLabel { + primary: label, + detail_left, + detail_right: self.detail.clone(), + }, text_edit, is_snippet: self.is_snippet, detail: self.detail, |