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.rs56
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,