aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-05-14 14:15:52 +0100
committerAleksey Kladov <[email protected]>2020-05-14 14:15:52 +0100
commit90c62bcee9d1950d0e4b642fc2bd3ae5374e40cb (patch)
treefeb465bcaa569115f3d7b5fab74ba395c8d9940d
parentf1587ac26332c3378c41d3cc552b270ee6a45cc4 (diff)
Prioritize locals with correct types
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs2
-rw-r--r--crates/ra_ide/src/completion/presentation.rs58
2 files changed, 55 insertions, 5 deletions
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs
index b6b9627de..da336973c 100644
--- a/crates/ra_ide/src/completion/completion_context.rs
+++ b/crates/ra_ide/src/completion/completion_context.rs
@@ -34,7 +34,7 @@ pub(crate) struct CompletionContext<'a> {
34 pub(super) record_pat_syntax: Option<ast::RecordPat>, 34 pub(super) record_pat_syntax: Option<ast::RecordPat>,
35 pub(super) record_field_syntax: Option<ast::RecordField>, 35 pub(super) record_field_syntax: Option<ast::RecordField>,
36 pub(super) impl_def: Option<ast::ImplDef>, 36 pub(super) impl_def: Option<ast::ImplDef>,
37 /// FIXME: `ActiveParameter` is string-based, which is very wrong 37 /// FIXME: `ActiveParameter` is string-based, which is very very wrong
38 pub(super) active_parameter: Option<ActiveParameter>, 38 pub(super) active_parameter: Option<ActiveParameter>,
39 pub(super) is_param: bool, 39 pub(super) is_param: bool,
40 /// If a name-binding or reference to a const in a pattern. 40 /// If a name-binding or reference to a const in a pattern.
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index 2edb130cf..077cf9647 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -17,12 +17,11 @@ use crate::{
17impl Completions { 17impl Completions {
18 pub(crate) fn add_field(&mut self, ctx: &CompletionContext, field: hir::Field, ty: &Type) { 18 pub(crate) fn add_field(&mut self, ctx: &CompletionContext, field: hir::Field, ty: &Type) {
19 let is_deprecated = is_deprecated(field, ctx.db); 19 let is_deprecated = is_deprecated(field, ctx.db);
20 let ty = ty.display(ctx.db).to_string();
21 let name = field.name(ctx.db); 20 let name = field.name(ctx.db);
22 let mut completion_item = 21 let mut completion_item =
23 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string()) 22 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string())
24 .kind(CompletionItemKind::Field) 23 .kind(CompletionItemKind::Field)
25 .detail(ty.clone()) 24 .detail(ty.display(ctx.db).to_string())
26 .set_documentation(field.docs(ctx.db)) 25 .set_documentation(field.docs(ctx.db))
27 .set_deprecated(is_deprecated); 26 .set_deprecated(is_deprecated);
28 27
@@ -107,6 +106,12 @@ impl Completions {
107 } 106 }
108 }; 107 };
109 108
109 if let ScopeDef::Local(local) = resolution {
110 if let Some(score) = compute_score(ctx, &local.ty(ctx.db), &local_name) {
111 completion_item = completion_item.set_score(score);
112 }
113 }
114
110 // Add `<>` for generic types 115 // Add `<>` for generic types
111 if ctx.is_path_type && !ctx.has_type_args && ctx.config.add_call_parenthesis { 116 if ctx.is_path_type && !ctx.has_type_args && ctx.config.add_call_parenthesis {
112 if let Some(cap) = ctx.config.snippet_cap { 117 if let Some(cap) = ctx.config.snippet_cap {
@@ -319,10 +324,11 @@ impl Completions {
319 324
320pub(crate) fn compute_score( 325pub(crate) fn compute_score(
321 ctx: &CompletionContext, 326 ctx: &CompletionContext,
322 // FIXME: this definitely should be a `Type` 327 ty: &Type,
323 ty: &str,
324 name: &str, 328 name: &str,
325) -> Option<CompletionScore> { 329) -> Option<CompletionScore> {
330 // FIXME: this should not fall back to string equality.
331 let ty = &ty.display(ctx.db).to_string();
326 let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax { 332 let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax {
327 tested_by!(test_struct_field_completion_in_record_lit); 333 tested_by!(test_struct_field_completion_in_record_lit);
328 let (struct_field, _local) = ctx.sema.resolve_record_field(record_field)?; 334 let (struct_field, _local) = ctx.sema.resolve_record_field(record_field)?;
@@ -1405,4 +1411,48 @@ mod tests {
1405 "### 1411 "###
1406 ); 1412 );
1407 } 1413 }
1414
1415 #[test]
1416 fn prioritize_exact_ref_match() {
1417 assert_debug_snapshot!(
1418 do_reference_completion(
1419 r"
1420 struct WorldSnapshot { _f: () };
1421 fn go(world: &WorldSnapshot) {
1422 go(w<|>)
1423 }
1424 ",
1425 ),
1426 @r###"
1427 [
1428 CompletionItem {
1429 label: "WorldSnapshot",
1430 source_range: 132..133,
1431 delete: 132..133,
1432 insert: "WorldSnapshot",
1433 kind: Struct,
1434 },
1435 CompletionItem {
1436 label: "go(…)",
1437 source_range: 132..133,
1438 delete: 132..133,
1439 insert: "go(${1:world})$0",
1440 kind: Function,
1441 lookup: "go",
1442 detail: "fn go(world: &WorldSnapshot)",
1443 trigger_call_info: true,
1444 },
1445 CompletionItem {
1446 label: "world",
1447 source_range: 132..133,
1448 delete: 132..133,
1449 insert: "world",
1450 kind: Binding,
1451 detail: "&WorldSnapshot",
1452 score: TypeAndNameMatch,
1453 },
1454 ]
1455 "###
1456 );
1457 }
1408} 1458}