Skip to content

Commit 4901ea3

Browse files
committed
Lookup lang attribute on assoc item trait directly
1 parent 94b369f commit 4901ea3

File tree

4 files changed

+67
-54
lines changed

4 files changed

+67
-54
lines changed

crates/hir_def/src/attr.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,10 @@ impl Attrs {
255255
}
256256
}
257257

258+
pub fn lang(&self) -> Option<&SmolStr> {
259+
self.by_key("lang").string_value()
260+
}
261+
258262
pub fn docs(&self) -> Option<Documentation> {
259263
let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_deref()? {
260264
AttrInput::Literal(s) => Some(s),
@@ -754,20 +758,20 @@ impl Attr {
754758
}
755759

756760
#[derive(Debug, Clone, Copy)]
757-
pub struct AttrQuery<'a> {
758-
attrs: &'a Attrs,
761+
pub struct AttrQuery<'attr> {
762+
attrs: &'attr Attrs,
759763
key: &'static str,
760764
}
761765

762-
impl<'a> AttrQuery<'a> {
763-
pub fn tt_values(self) -> impl Iterator<Item = &'a Subtree> {
766+
impl<'attr> AttrQuery<'attr> {
767+
pub fn tt_values(self) -> impl Iterator<Item = &'attr Subtree> {
764768
self.attrs().filter_map(|attr| match attr.input.as_deref()? {
765769
AttrInput::TokenTree(it, _) => Some(it),
766770
_ => None,
767771
})
768772
}
769773

770-
pub fn string_value(self) -> Option<&'a SmolStr> {
774+
pub fn string_value(self) -> Option<&'attr SmolStr> {
771775
self.attrs().find_map(|attr| match attr.input.as_deref()? {
772776
AttrInput::Literal(it) => Some(it),
773777
_ => None,
@@ -778,7 +782,7 @@ impl<'a> AttrQuery<'a> {
778782
self.attrs().next().is_some()
779783
}
780784

781-
pub fn attrs(self) -> impl Iterator<Item = &'a Attr> + Clone {
785+
pub fn attrs(self) -> impl Iterator<Item = &'attr Attr> + Clone {
782786
let key = self.key;
783787
self.attrs
784788
.iter()

crates/ide_completion/src/context.rs

Lines changed: 35 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@
33
use std::iter;
44

55
use base_db::SourceDatabaseExt;
6-
use hir::{known, Local, Name, ScopeDef, Semantics, SemanticsScope, Type, TypeInfo};
6+
use hir::{HasAttrs, Local, Name, ScopeDef, Semantics, SemanticsScope, Type, TypeInfo};
77
use ide_db::{
88
active_parameter::ActiveParameter,
99
base_db::{FilePosition, SourceDatabase},
1010
helpers::FamousDefs,
1111
RootDatabase,
1212
};
13-
use rustc_hash::FxHashSet;
1413
use syntax::{
1514
algo::find_node_at_offset,
1615
ast::{self, HasName, NameOrNameRef},
@@ -124,8 +123,6 @@ pub(crate) struct CompletionContext<'a> {
124123
pub(super) path_context: Option<PathCompletionContext>,
125124

126125
pub(super) locals: Vec<(Name, Local)>,
127-
/// Operator traits defined in the project
128-
pub(super) ops_traits: FxHashSet<hir::Trait>,
129126

130127
no_completion_required: bool,
131128
}
@@ -315,7 +312,10 @@ impl<'a> CompletionContext<'a> {
315312

316313
/// Whether the given trait is an operator trait or not.
317314
pub(crate) fn is_ops_trait(&self, trait_: hir::Trait) -> bool {
318-
self.ops_traits.contains(&trait_)
315+
match trait_.attrs(self.db).lang() {
316+
Some(lang) => OP_TRAIT_LANG_NAMES.contains(&lang.as_str()),
317+
None => false,
318+
}
319319
}
320320

321321
/// A version of [`SemanticsScope::process_all_names`] that filters out `#[doc(hidden)]` items.
@@ -398,16 +398,6 @@ impl<'a> CompletionContext<'a> {
398398
locals.push((name, local));
399399
}
400400
});
401-
let mut ops_traits =
402-
FxHashSet::with_capacity_and_hasher(OP_TRAIT_LANG_NAMES.len(), Default::default());
403-
if let Some(krate) = krate {
404-
let _p = profile::span("CompletionContext::new ops");
405-
for trait_ in
406-
OP_TRAIT_LANG_NAMES.iter().filter_map(|item| hir::Trait::lang(db, krate, item))
407-
{
408-
ops_traits.insert(trait_);
409-
}
410-
}
411401

412402
let mut ctx = CompletionContext {
413403
sema,
@@ -434,7 +424,6 @@ impl<'a> CompletionContext<'a> {
434424
locals,
435425
incomplete_let: false,
436426
no_completion_required: false,
437-
ops_traits,
438427
};
439428
ctx.expand_and_fill(
440429
original_file.syntax().clone(),
@@ -938,36 +927,36 @@ fn has_ref(token: &SyntaxToken) -> bool {
938927
token.kind() == T![&]
939928
}
940929

941-
const OP_TRAIT_LANG_NAMES: &[hir::Name] = &[
942-
known::add_assign,
943-
known::add,
944-
known::bitand_assign,
945-
known::bitand,
946-
known::bitor_assign,
947-
known::bitor,
948-
known::bitxor_assign,
949-
known::bitxor,
950-
known::deref_mut,
951-
known::deref,
952-
known::div_assign,
953-
known::div,
954-
known::fn_mut,
955-
known::fn_once,
956-
known::r#fn,
957-
known::index_mut,
958-
known::index,
959-
known::mul_assign,
960-
known::mul,
961-
known::neg,
962-
known::not,
963-
known::rem_assign,
964-
known::rem,
965-
known::shl_assign,
966-
known::shl,
967-
known::shr_assign,
968-
known::shr,
969-
known::sub,
970-
known::sub,
930+
const OP_TRAIT_LANG_NAMES: &[&str] = &[
931+
"add_assign",
932+
"add",
933+
"bitand_assign",
934+
"bitand",
935+
"bitor_assign",
936+
"bitor",
937+
"bitxor_assign",
938+
"bitxor",
939+
"deref_mut",
940+
"deref",
941+
"div_assign",
942+
"div",
943+
"fn_mut",
944+
"fn_once",
945+
"fn",
946+
"index_mut",
947+
"index",
948+
"mul_assign",
949+
"mul",
950+
"neg",
951+
"not",
952+
"rem_assign",
953+
"rem",
954+
"shl_assign",
955+
"shl",
956+
"shr_assign",
957+
"shr",
958+
"sub",
959+
"sub",
971960
];
972961
#[cfg(test)]
973962
mod tests {

crates/ide_completion/src/item.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ pub enum CompletionRelevanceTypeMatch {
177177
}
178178

179179
impl CompletionRelevance {
180+
const BASE_LINE: u32 = 1;
180181
/// Provides a relevance score. Higher values are more relevant.
181182
///
182183
/// The absolute value of the relevance score is not meaningful, for
@@ -187,7 +188,7 @@ impl CompletionRelevance {
187188
/// See is_relevant if you need to make some judgement about score
188189
/// in an absolute sense.
189190
pub fn score(&self) -> u32 {
190-
let mut score = 0;
191+
let mut score = Self::BASE_LINE;
191192

192193
if self.exact_name_match {
193194
score += 1;
@@ -213,7 +214,7 @@ impl CompletionRelevance {
213214
/// some threshold such that we think it is especially likely
214215
/// to be relevant.
215216
pub fn is_relevant(&self) -> bool {
216-
self.score() > 0
217+
self.score() > (Self::BASE_LINE + 1)
217218
}
218219
}
219220

@@ -563,6 +564,7 @@ mod tests {
563564
// This test asserts that the relevance score for these items is ascending, and
564565
// that any items in the same vec have the same score.
565566
let expected_relevance_order = vec![
567+
vec![CompletionRelevance { is_op_method: true, ..CompletionRelevance::default() }],
566568
vec![CompletionRelevance::default()],
567569
vec![
568570
CompletionRelevance { exact_name_match: true, ..CompletionRelevance::default() },

crates/ide_completion/src/render.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ mod tests {
400400
(relevance.exact_name_match, "name"),
401401
(relevance.is_local, "local"),
402402
(relevance.exact_postfix_snippet_match, "snippet"),
403+
(relevance.is_op_method, "op_method"),
403404
]
404405
.into_iter()
405406
.filter_map(|(cond, desc)| if cond { Some(desc) } else { None })
@@ -1352,6 +1353,23 @@ fn main() {
13521353
)
13531354
}
13541355

1356+
#[test]
1357+
fn op_method_relevances() {
1358+
check_relevance(
1359+
r#"
1360+
#[lang = "sub"]
1361+
trait Sub {
1362+
fn sub(self, other: Self) -> Self { self }
1363+
}
1364+
impl Sub for u32 {}
1365+
fn foo(a: u32) { a.$0 }
1366+
"#,
1367+
expect![[r#"
1368+
me sub(…) (as Sub) [op_method]
1369+
"#]],
1370+
)
1371+
}
1372+
13551373
#[test]
13561374
fn struct_field_method_ref() {
13571375
check_kinds(

0 commit comments

Comments
 (0)