Skip to content

Commit 550638b

Browse files
committed
Refactor completion relevance calculation
1 parent 36874a3 commit 550638b

File tree

3 files changed

+35
-66
lines changed

3 files changed

+35
-66
lines changed

crates/ide-completion/src/completions.rs

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -694,10 +694,6 @@ pub(super) fn complete_name_ref(
694694
dot::complete_undotted_self(acc, ctx, path_ctx, expr_ctx);
695695
item_list::complete_item_list_in_expr(acc, ctx, path_ctx, expr_ctx);
696696
snippet::complete_expr_snippet(acc, ctx, path_ctx, expr_ctx);
697-
698-
if matches!(ctx.token.kind(), syntax::SyntaxKind::COLON2) {
699-
bump_relevance_for_new_like_fns(acc);
700-
}
701697
}
702698
PathKind::Type { location } => {
703699
r#type::complete_type_path(acc, ctx, path_ctx, location);
@@ -771,37 +767,3 @@ fn complete_patterns(
771767
pattern::complete_pattern(acc, ctx, pattern_ctx);
772768
record::complete_record_pattern_fields(acc, ctx, pattern_ctx);
773769
}
774-
775-
/// Sort the suggestions with `new` like functions first.
776-
/// That means:
777-
/// fn with no param that returns itself
778-
/// fn with param that returns itself
779-
pub(crate) fn bump_relevance_for_new_like_fns(acc: &mut Completions) {
780-
// ToDo: Ensure these fn returns Self
781-
fn maybe_new(item: &CompletionItem) -> bool {
782-
item.detail.as_ref().map(|d| d.starts_with("fn() -> ")).unwrap_or_default()
783-
}
784-
fn maybe_new_with_args(item: &CompletionItem) -> bool {
785-
item.detail
786-
.as_ref()
787-
.map(|d| d.starts_with("fn(") && d.contains("->") && !d.contains("&self"))
788-
.unwrap_or_default()
789-
}
790-
791-
fn maybe_builder(item: &CompletionItem) -> bool {
792-
item.detail
793-
.as_ref()
794-
.map(|d| d.starts_with("fn() -> ") && d.contains("Builder"))
795-
.unwrap_or_default()
796-
}
797-
798-
for item in acc.buf.iter_mut() {
799-
if maybe_new(&item) {
800-
item.bump_relevance_by(30);
801-
} else if maybe_builder(&item) {
802-
item.bump_relevance_by(20);
803-
} else if maybe_new_with_args(&item) {
804-
item.bump_relevance_by(10);
805-
}
806-
}
807-
}

crates/ide-completion/src/render.rs

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use ide_db::{
1717
imports::import_assets::LocatedImport,
1818
RootDatabase, SnippetCap, SymbolKind,
1919
};
20-
use syntax::{AstNode, SmolStr, SyntaxKind, TextRange};
20+
use syntax::{AstNode, SmolStr, SyntaxKind, SyntaxToken, TextRange};
2121
use text_edit::TextEdit;
2222

2323
use crate::{
@@ -72,6 +72,10 @@ impl<'a> RenderContext<'a> {
7272
self.completion.db
7373
}
7474

75+
fn token(&self) -> &SyntaxToken {
76+
&self.completion.token
77+
}
78+
7579
fn source_range(&self) -> TextRange {
7680
self.completion.source_range()
7781
}
@@ -2033,33 +2037,6 @@ fn test() {
20332037
me foo(…) [type_could_unify]
20342038
"#]],
20352039
);
2036-
2037-
check_relevance(
2038-
r#"
2039-
struct A;
2040-
struct ABuilder;
2041-
impl A {
2042-
fn foo(&self) {}
2043-
fn new_1(input: u32) -> A { A }
2044-
fn new_2() -> Self { A }
2045-
fn aaaabuilder() -> ABuilder { A }
2046-
fn test() {
2047-
Self::$0;
2048-
}
2049-
}
2050-
"#,
2051-
// preference:
2052-
// fn with no param that returns itself
2053-
// builder like fn
2054-
// fn with param that returns itself
2055-
expect![[r#"
2056-
fn new_2() []
2057-
fn aaaabuilder() []
2058-
fn new_1(…) []
2059-
me foo(…) []
2060-
fn test() []
2061-
"#]],
2062-
);
20632040
}
20642041

20652042
#[test]

crates/ide-completion/src/render/function.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ fn render(
105105
},
106106
exact_name_match: compute_exact_name_match(completion, &call),
107107
is_op_method,
108+
bonus_score: calculate_bonus(&ctx, func, db),
108109
..ctx.completion_relevance()
109110
});
110111

@@ -153,6 +154,33 @@ fn render(
153154
item
154155
}
155156

157+
/// When typing `::` of a type, the preferred orderer is:
158+
/// * Constructors: new like functions to be able to create the type,
159+
/// * Constructors that take args: Any other function that creates Self
160+
/// * Builder Methods: any builder methods available
161+
/// * Regular methods
162+
fn calculate_bonus(ctx: &RenderContext<'_>, func: hir::Function, db: &dyn HirDatabase) -> u32 {
163+
if ctx.token().kind() != syntax::SyntaxKind::COLON2 || func.self_param(db).is_some() {
164+
return 0;
165+
}
166+
167+
let mut bonus = 0;
168+
169+
let has_args = !func.assoc_fn_params(db).is_empty();
170+
let ret_type = func.ret_type(db);
171+
if !has_args && !ret_type.is_unit() {
172+
// fn() -> A
173+
bonus += 30;
174+
} else if has_args && !ret_type.is_unit() {
175+
// fn(..) -> A
176+
bonus += 20;
177+
} else if !has_args && ret_type.display(db).to_string().ends_with("Builder") {
178+
// -> [..]Builder
179+
bonus += 10;
180+
}
181+
bonus
182+
}
183+
156184
pub(super) fn add_call_parens<'b>(
157185
builder: &'b mut Builder,
158186
ctx: &CompletionContext<'_>,
@@ -213,6 +241,7 @@ pub(super) fn add_call_parens<'b>(
213241

214242
(snippet, "(…)")
215243
};
244+
216245
builder.label(SmolStr::from_iter([&name, label_suffix])).insert_snippet(cap, snippet)
217246
}
218247

@@ -256,6 +285,7 @@ fn detail(db: &dyn HirDatabase, func: hir::Function) -> String {
256285
if !ret_ty.is_unit() {
257286
format_to!(detail, " -> {}", ret_ty.display(db));
258287
}
288+
259289
detail
260290
}
261291

0 commit comments

Comments
 (0)