Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions crates/hir-def/src/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,13 @@ impl Attrs {
})
}

pub fn has_doc_notable_trait(&self) -> bool {
self.by_key("doc").tt_values().any(|tt| {
tt.delimiter.kind == DelimiterKind::Parenthesis &&
matches!(&*tt.token_trees, [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.text == "notable_trait")
})
}

pub fn doc_exprs(&self) -> impl Iterator<Item = DocExpr> + '_ {
self.by_key("doc").tt_values().map(DocExpr::parse)
}
Expand Down
5 changes: 5 additions & 0 deletions crates/ide-completion/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,11 @@ impl CompletionContext<'_> {
}
}

/// Whether the given trait has `#[doc(notable_trait)]`
pub(crate) fn is_doc_notable_trait(&self, trait_: hir::Trait) -> bool {
trait_.attrs(self.db).has_doc_notable_trait()
}

/// Returns the traits in scope, with the [`Drop`] trait removed.
pub(crate) fn traits_in_scope(&self) -> hir::VisibleTraits {
let mut traits_in_scope = self.scope.visible_traits();
Expand Down
6 changes: 6 additions & 0 deletions crates/ide-completion/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ pub struct CompletionRelevance {
pub is_local: bool,
/// This is set when trait items are completed in an impl of that trait.
pub is_item_from_trait: bool,
/// This is set for when trait items are from traits with `#[doc(notable_trait)]`
pub is_item_from_notable_trait: bool,
/// This is set when an import is suggested whose name is already imported.
pub is_name_already_imported: bool,
/// This is set for completions that will insert a `use` item.
Expand Down Expand Up @@ -228,6 +230,7 @@ impl CompletionRelevance {
is_private_editable,
postfix_match,
is_definite,
is_item_from_notable_trait,
} = self;

// lower rank private things
Expand Down Expand Up @@ -266,6 +269,9 @@ impl CompletionRelevance {
if is_item_from_trait {
score += 1;
}
if is_item_from_notable_trait {
score += 1;
}
if is_definite {
score += 10;
}
Expand Down
81 changes: 81 additions & 0 deletions crates/ide-completion/src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,7 @@ fn main() { let _: m::Spam = S$0 }
),
is_local: false,
is_item_from_trait: false,
is_item_from_notable_trait: false,
is_name_already_imported: false,
requires_import: false,
is_op_method: false,
Expand All @@ -1196,6 +1197,7 @@ fn main() { let _: m::Spam = S$0 }
),
is_local: false,
is_item_from_trait: false,
is_item_from_notable_trait: false,
is_name_already_imported: false,
requires_import: false,
is_op_method: false,
Expand Down Expand Up @@ -1274,6 +1276,7 @@ fn foo() { A { the$0 } }
),
is_local: false,
is_item_from_trait: false,
is_item_from_notable_trait: false,
is_name_already_imported: false,
requires_import: false,
is_op_method: false,
Expand Down Expand Up @@ -2089,6 +2092,7 @@ fn foo() {
),
is_local: false,
is_item_from_trait: false,
is_item_from_notable_trait: false,
is_name_already_imported: false,
requires_import: false,
is_op_method: false,
Expand Down Expand Up @@ -2439,4 +2443,81 @@ impl S {
"#,
)
}

#[test]
fn notable_traits_method_relevance() {
check_kinds(
r#"
#[doc(notable_trait)]
trait Write {
fn write(&self);
fn flush(&self);
}

struct Writer;

impl Write for Writer {
fn write(&self) {}
fn flush(&self) {}
}

fn main() {
Writer.$0
}
"#,
&[
CompletionItemKind::Method,
CompletionItemKind::SymbolKind(SymbolKind::Field),
CompletionItemKind::SymbolKind(SymbolKind::Function),
],
expect![[r#"
[
CompletionItem {
label: "flush()",
source_range: 193..193,
delete: 193..193,
insert: "flush()$0",
kind: Method,
lookup: "flush",
detail: "fn(&self)",
relevance: CompletionRelevance {
exact_name_match: false,
type_match: None,
is_local: false,
is_item_from_trait: false,
is_item_from_notable_trait: true,
is_name_already_imported: false,
requires_import: false,
is_op_method: false,
is_private_editable: false,
postfix_match: None,
is_definite: false,
},
},
CompletionItem {
label: "write()",
source_range: 193..193,
delete: 193..193,
insert: "write()$0",
kind: Method,
lookup: "write",
detail: "fn(&self)",
relevance: CompletionRelevance {
exact_name_match: false,
type_match: None,
is_local: false,
is_item_from_trait: false,
is_item_from_notable_trait: true,
is_name_already_imported: false,
requires_import: false,
is_op_method: false,
is_private_editable: false,
postfix_match: None,
is_definite: false,
},
},
]
"#]],
);
}
}
14 changes: 9 additions & 5 deletions crates/ide-completion/src/render/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,13 @@ fn render(
);

let ret_type = func.ret_type(db);
let is_op_method = func
.as_assoc_item(ctx.db())
.and_then(|trait_| trait_.containing_trait_or_trait_impl(ctx.db()))
.map_or(false, |trait_| completion.is_ops_trait(trait_));
let assoc_item = func.as_assoc_item(db);

let trait_ = assoc_item.and_then(|trait_| trait_.containing_trait_or_trait_impl(db));
let is_op_method = trait_.map_or(false, |trait_| completion.is_ops_trait(trait_));

let is_item_from_notable_trait =
trait_.map_or(false, |trait_| completion.is_doc_notable_trait(trait_));

let (has_dot_receiver, has_call_parens, cap) = match func_kind {
FuncKind::Function(&PathCompletionCtx {
Expand Down Expand Up @@ -105,6 +108,7 @@ fn render(
},
exact_name_match: compute_exact_name_match(completion, &call),
is_op_method,
is_item_from_notable_trait,
..ctx.completion_relevance()
});

Expand Down Expand Up @@ -141,7 +145,7 @@ fn render(
item.add_import(import_to_add);
}
None => {
if let Some(actm) = func.as_assoc_item(db) {
if let Some(actm) = assoc_item {
if let Some(trt) = actm.containing_trait_or_trait_impl(db) {
item.trait_name(trt.name(db).to_smol_str());
}
Expand Down