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 | 66 |
1 files changed, 50 insertions, 16 deletions
diff --git a/crates/ide-completion/src/item.rs b/crates/ide-completion/src/item.rs index 1a9139d855..6abf4f632a 100644 --- a/crates/ide-completion/src/item.rs +++ b/crates/ide-completion/src/item.rs @@ -84,7 +84,15 @@ pub struct CompletionItem { pub ref_match: Option<(CompletionItemRefMode, TextSize)>, /// The import data to add to completion's edits. - pub import_to_add: SmallVec<[String; 1]>, + pub import_to_add: SmallVec<[CompletionItemImport; 1]>, +} + +#[derive(Clone, UpmapFromRaFixture)] +pub struct CompletionItemImport { + /// The path to import. + pub path: String, + /// Whether to import `as _`. + pub as_underscore: bool, } #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] @@ -184,6 +192,8 @@ pub struct CompletionRelevance { pub function: Option<CompletionRelevanceFn>, /// true when there is an `await.method()` or `iter().method()` completion. pub is_skipping_completion: bool, + /// if inherent impl already exists in current module, user may not want to implement it again. + pub has_local_inherent_impl: bool, } #[derive(Debug, Clone, Copy, Eq, PartialEq)] pub struct CompletionRelevanceTraitInfo { @@ -275,6 +285,7 @@ impl CompletionRelevance { trait_, function, is_skipping_completion, + has_local_inherent_impl, } = self; // only applicable for completions within use items @@ -347,6 +358,10 @@ impl CompletionRelevance { score += fn_score; }; + if has_local_inherent_impl { + score -= 5; + } + score } @@ -450,6 +465,7 @@ impl CompletionItem { ref_match: None, imports_to_add: Default::default(), doc_aliases: vec![], + adds_text: None, edition, } } @@ -480,12 +496,13 @@ impl CompletionItem { /// A helper to make `CompletionItem`s. #[must_use] -#[derive(Clone)] +#[derive(Debug, Clone)] pub(crate) struct Builder { source_range: TextRange, imports_to_add: SmallVec<[LocatedImport; 1]>, trait_name: Option<SmolStr>, doc_aliases: Vec<SmolStr>, + adds_text: Option<SmolStr>, label: SmolStr, insert_text: Option<String>, is_snippet: bool, @@ -526,9 +543,16 @@ impl Builder { let insert_text = self.insert_text.unwrap_or_else(|| label.to_string()); let mut detail_left = None; + let mut to_detail_left = |args: fmt::Arguments<'_>| { + let detail_left = detail_left.get_or_insert_with(String::new); + if !detail_left.is_empty() { + detail_left.push(' '); + } + format_to!(detail_left, "{args}") + }; if !self.doc_aliases.is_empty() { let doc_aliases = self.doc_aliases.iter().join(", "); - detail_left = Some(format!("(alias {doc_aliases})")); + to_detail_left(format_args!("(alias {doc_aliases})")); let lookup_doc_aliases = self .doc_aliases .iter() @@ -548,22 +572,17 @@ impl Builder { lookup = format_smolstr!("{lookup}{lookup_doc_aliases}"); } } + if let Some(adds_text) = self.adds_text { + to_detail_left(format_args!("(adds {})", adds_text.trim())); + } if let [import_edit] = &*self.imports_to_add { // snippets can have multiple imports, but normal completions only have up to one - let detail_left = detail_left.get_or_insert_with(String::new); - format_to!( - detail_left, - "{}(use {})", - if detail_left.is_empty() { "" } else { " " }, + to_detail_left(format_args!( + "(use {})", import_edit.import_path.display(db, self.edition) - ); + )); } else if let Some(trait_name) = self.trait_name { - let detail_left = detail_left.get_or_insert_with(String::new); - format_to!( - detail_left, - "{}(as {trait_name})", - if detail_left.is_empty() { "" } else { " " }, - ); + to_detail_left(format_args!("(as {trait_name})")); } let text_edit = match self.text_edit { @@ -574,7 +593,18 @@ impl Builder { let import_to_add = self .imports_to_add .into_iter() - .map(|import| import.import_path.display(db, self.edition).to_string()) + .map(|import| { + let path = import.import_path.display(db, self.edition).to_string(); + let as_underscore = + if let hir::ItemInNs::Types(hir::ModuleDef::Trait(trait_to_import)) = + import.item_to_import + { + trait_to_import.prefer_underscore_import(db) + } else { + false + }; + CompletionItemImport { path, as_underscore } + }) .collect(); CompletionItem { @@ -613,6 +643,10 @@ impl Builder { self.doc_aliases = doc_aliases; self } + pub(crate) fn adds_text(&mut self, adds_text: SmolStr) -> &mut Builder { + self.adds_text = Some(adds_text); + self + } pub(crate) fn insert_text(&mut self, insert_text: impl Into<String>) -> &mut Builder { self.insert_text = Some(insert_text.into()); self |