Skip to content

Commit ca0633c

Browse files
committed
feat: Deprioritize ops methods in completion
1 parent 41a0e95 commit ca0633c

File tree

6 files changed

+106
-30
lines changed

6 files changed

+106
-30
lines changed

crates/hir/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,6 +1610,12 @@ pub struct Trait {
16101610
}
16111611

16121612
impl Trait {
1613+
pub fn lang(db: &dyn HirDatabase, krate: Crate, name: &Name) -> Option<Trait> {
1614+
db.lang_item(krate.into(), name.to_smol_str())
1615+
.and_then(LangItemTarget::as_trait)
1616+
.map(Into::into)
1617+
}
1618+
16131619
pub fn module(self, db: &dyn HirDatabase) -> Module {
16141620
Module { id: self.id.lookup(db.upcast()).container }
16151621
}

crates/hir_def/src/lang_item.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,8 @@ impl LangItems {
144144
let _p = profile::span("lang_item_query");
145145
let lang_items = db.crate_lang_items(start_crate);
146146
let start_crate_target = lang_items.items.get(&item);
147-
if let Some(target) = start_crate_target {
148-
return Some(*target);
147+
if let Some(&target) = start_crate_target {
148+
return Some(target);
149149
}
150150
db.crate_graph()[start_crate]
151151
.dependencies

crates/hir_expand/src/name.rs

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -309,39 +309,45 @@ pub mod known {
309309
wrapping_mul,
310310
wrapping_sub,
311311
// known methods of lang items
312-
add,
313-
mul,
314-
sub,
315-
div,
316-
rem,
317-
shl,
318-
shr,
319-
bitxor,
320-
bitor,
321-
bitand,
322-
add_assign,
323-
mul_assign,
324-
sub_assign,
325-
div_assign,
326-
rem_assign,
327-
shl_assign,
328-
shr_assign,
329-
bitxor_assign,
330-
bitor_assign,
331-
bitand_assign,
332312
eq,
333313
ne,
334314
ge,
335315
gt,
336316
le,
337317
lt,
338318
// lang items
339-
not,
340-
neg,
319+
add_assign,
320+
add,
321+
bitand_assign,
322+
bitand,
323+
bitor_assign,
324+
bitor,
325+
bitxor_assign,
326+
bitxor,
327+
deref_mut,
328+
deref,
329+
div_assign,
330+
div,
331+
fn_mut,
332+
fn_once,
341333
future_trait,
342-
owned_box,
343334
index,
344-
partial_ord
335+
index_mut,
336+
mul_assign,
337+
mul,
338+
neg,
339+
not,
340+
owned_box,
341+
partial_ord,
342+
r#fn,
343+
rem_assign,
344+
rem,
345+
shl_assign,
346+
shl,
347+
shr_assign,
348+
shr,
349+
sub_assign,
350+
sub,
345351
);
346352

347353
// self/Self cannot be used as an identifier

crates/ide_completion/src/context.rs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
use std::iter;
44

55
use base_db::SourceDatabaseExt;
6-
use hir::{Local, Name, ScopeDef, Semantics, SemanticsScope, Type, TypeInfo};
6+
use hir::{known, 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;
1314
use syntax::{
1415
algo::find_node_at_offset,
1516
ast::{self, HasName, NameOrNameRef},
@@ -85,6 +86,7 @@ pub(crate) enum ParamKind {
8586
Function,
8687
Closure,
8788
}
89+
8890
/// `CompletionContext` is created early during completion to figure out, where
8991
/// exactly is the cursor, syntax-wise.
9092
#[derive(Debug)]
@@ -120,7 +122,10 @@ pub(crate) struct CompletionContext<'a> {
120122
pub(super) lifetime_ctx: Option<LifetimeContext>,
121123
pub(super) pattern_ctx: Option<PatternContext>,
122124
pub(super) path_context: Option<PathCompletionContext>,
125+
123126
pub(super) locals: Vec<(Name, Local)>,
127+
/// Operator traits defined in the project
128+
pub(super) ops_traits: FxHashSet<hir::Trait>,
124129

125130
no_completion_required: bool,
126131
}
@@ -308,6 +313,11 @@ impl<'a> CompletionContext<'a> {
308313
self.token.kind() == BANG && self.token.parent().map_or(false, |it| it.kind() == MACRO_CALL)
309314
}
310315

316+
/// Whether the given trait is an operator trait or not.
317+
pub(crate) fn is_ops_trait(&self, trait_: hir::Trait) -> bool {
318+
self.ops_traits.contains(&trait_)
319+
}
320+
311321
/// A version of [`SemanticsScope::process_all_names`] that filters out `#[doc(hidden)]` items.
312322
pub(crate) fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) {
313323
let _p = profile::span("CompletionContext::process_all_names");
@@ -388,6 +398,17 @@ impl<'a> CompletionContext<'a> {
388398
locals.push((name, local));
389399
}
390400
});
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+
}
411+
391412
let mut ctx = CompletionContext {
392413
sema,
393414
scope,
@@ -413,6 +434,7 @@ impl<'a> CompletionContext<'a> {
413434
locals,
414435
incomplete_let: false,
415436
no_completion_required: false,
437+
ops_traits,
416438
};
417439
ctx.expand_and_fill(
418440
original_file.syntax().clone(),
@@ -889,6 +911,7 @@ fn pattern_context_for(pat: ast::Pat) -> PatternContext {
889911
});
890912
PatternContext { refutability, is_param, has_type_ascription }
891913
}
914+
892915
fn find_node_with_range<N: AstNode>(syntax: &SyntaxNode, range: TextRange) -> Option<N> {
893916
syntax.covering_element(range).ancestors().find_map(N::cast)
894917
}
@@ -915,6 +938,37 @@ fn has_ref(token: &SyntaxToken) -> bool {
915938
token.kind() == T![&]
916939
}
917940

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,
971+
];
918972
#[cfg(test)]
919973
mod tests {
920974
use expect_test::{expect, Expect};

crates/ide_completion/src/item.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ pub struct CompletionRelevance {
139139
/// }
140140
/// ```
141141
pub is_local: bool,
142+
/// Set for method completions of the `core::ops` family.
143+
pub is_op_method: bool,
142144
/// This is set in cases like these:
143145
///
144146
/// ```
@@ -198,6 +200,9 @@ impl CompletionRelevance {
198200
if self.is_local {
199201
score += 1;
200202
}
203+
if self.is_op_method {
204+
score -= 1;
205+
}
201206
if self.exact_postfix_snippet_match {
202207
score += 100;
203208
}
@@ -588,10 +593,8 @@ mod tests {
588593
..CompletionRelevance::default()
589594
}],
590595
vec![CompletionRelevance {
591-
exact_name_match: false,
592-
type_match: None,
593-
is_local: false,
594596
exact_postfix_snippet_match: true,
597+
..CompletionRelevance::default()
595598
}],
596599
];
597600

crates/ide_completion/src/render/function.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@ fn render(
7070
item.set_relevance(CompletionRelevance {
7171
type_match: compute_type_match(completion, &ret_type),
7272
exact_name_match: compute_exact_name_match(completion, &call),
73+
is_op_method: match func_type {
74+
FuncType::Method(_) => func
75+
.as_assoc_item(ctx.db())
76+
.and_then(|trait_| trait_.containing_trait_or_trait_impl(ctx.db()))
77+
.map_or(false, |trait_| completion.is_ops_trait(trait_)),
78+
_ => false,
79+
},
7380
..CompletionRelevance::default()
7481
});
7582

0 commit comments

Comments
 (0)