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.rs66
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