diff options
author | Galilée 'Bill' Enguehard <[email protected]> | 2020-05-21 22:27:38 +0100 |
---|---|---|
committer | Galilée 'Bill' Enguehard <[email protected]> | 2020-05-21 22:27:38 +0100 |
commit | 7fece3bdd2450c0807f7dd742239cae95f0cc65e (patch) | |
tree | 866c4db826c959e79c63a6727bdb9f2c61e6fc4f /crates/ra_ide/src/completion/presentation.rs | |
parent | db926218b2082077750291f8426ddd28b284cd08 (diff) | |
parent | 59732df8d40dfadc6dcf5951265416576399712a (diff) |
Merge branch 'master' of github.com:rust-analyzer/rust-analyzer into modname_spacing
Diffstat (limited to 'crates/ra_ide/src/completion/presentation.rs')
-rw-r--r-- | crates/ra_ide/src/completion/presentation.rs | 82 |
1 files changed, 66 insertions, 16 deletions
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index 2edb130cf..440ffa31d 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use hir::{Docs, HasAttrs, HasSource, HirDisplay, ModPath, ScopeDef, StructKind, Type}; | 3 | use hir::{Docs, HasAttrs, HasSource, HirDisplay, ModPath, ScopeDef, StructKind, Type}; |
4 | use ra_syntax::ast::NameOwner; | 4 | use ra_syntax::ast::NameOwner; |
5 | use stdx::SepBy; | 5 | use stdx::SepBy; |
6 | use test_utils::tested_by; | 6 | use test_utils::mark; |
7 | 7 | ||
8 | use crate::{ | 8 | use crate::{ |
9 | completion::{ | 9 | completion::{ |
@@ -17,12 +17,11 @@ use crate::{ | |||
17 | impl Completions { | 17 | impl 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 { |
@@ -116,7 +121,7 @@ impl Completions { | |||
116 | _ => false, | 121 | _ => false, |
117 | }; | 122 | }; |
118 | if has_non_default_type_params { | 123 | if has_non_default_type_params { |
119 | tested_by!(inserts_angle_brackets_for_generics); | 124 | mark::hit!(inserts_angle_brackets_for_generics); |
120 | completion_item = completion_item | 125 | completion_item = completion_item |
121 | .lookup_by(local_name.clone()) | 126 | .lookup_by(local_name.clone()) |
122 | .label(format!("{}<…>", local_name)) | 127 | .label(format!("{}<…>", local_name)) |
@@ -171,7 +176,7 @@ impl Completions { | |||
171 | } | 176 | } |
172 | None if needs_bang => builder.insert_text(format!("{}!", name)), | 177 | None if needs_bang => builder.insert_text(format!("{}!", name)), |
173 | _ => { | 178 | _ => { |
174 | tested_by!(dont_insert_macro_call_parens_unncessary); | 179 | mark::hit!(dont_insert_macro_call_parens_unncessary); |
175 | builder.insert_text(name) | 180 | builder.insert_text(name) |
176 | } | 181 | } |
177 | }; | 182 | }; |
@@ -319,19 +324,20 @@ impl Completions { | |||
319 | 324 | ||
320 | pub(crate) fn compute_score( | 325 | pub(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 | mark::hit!(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)?; |
329 | ( | 335 | ( |
330 | struct_field.name(ctx.db).to_string(), | 336 | struct_field.name(ctx.db).to_string(), |
331 | struct_field.signature_ty(ctx.db).display(ctx.db).to_string(), | 337 | struct_field.signature_ty(ctx.db).display(ctx.db).to_string(), |
332 | ) | 338 | ) |
333 | } else if let Some(active_parameter) = &ctx.active_parameter { | 339 | } else if let Some(active_parameter) = &ctx.active_parameter { |
334 | tested_by!(test_struct_field_completion_in_func_call); | 340 | mark::hit!(test_struct_field_completion_in_func_call); |
335 | (active_parameter.name.clone(), active_parameter.ty.clone()) | 341 | (active_parameter.name.clone(), active_parameter.ty.clone()) |
336 | } else { | 342 | } else { |
337 | return None; | 343 | return None; |
@@ -392,7 +398,7 @@ impl Builder { | |||
392 | None => return self, | 398 | None => return self, |
393 | }; | 399 | }; |
394 | // If not an import, add parenthesis automatically. | 400 | // If not an import, add parenthesis automatically. |
395 | tested_by!(inserts_parens_for_function_calls); | 401 | mark::hit!(inserts_parens_for_function_calls); |
396 | 402 | ||
397 | let (snippet, label) = if params.is_empty() { | 403 | let (snippet, label) = if params.is_empty() { |
398 | (format!("{}()$0", name), format!("{}()", name)) | 404 | (format!("{}()$0", name), format!("{}()", name)) |
@@ -451,7 +457,7 @@ fn guess_macro_braces(macro_name: &str, docs: &str) -> (&'static str, &'static s | |||
451 | #[cfg(test)] | 457 | #[cfg(test)] |
452 | mod tests { | 458 | mod tests { |
453 | use insta::assert_debug_snapshot; | 459 | use insta::assert_debug_snapshot; |
454 | use test_utils::covers; | 460 | use test_utils::mark; |
455 | 461 | ||
456 | use crate::completion::{ | 462 | use crate::completion::{ |
457 | test_utils::{do_completion, do_completion_with_options}, | 463 | test_utils::{do_completion, do_completion_with_options}, |
@@ -601,7 +607,7 @@ mod tests { | |||
601 | 607 | ||
602 | #[test] | 608 | #[test] |
603 | fn inserts_parens_for_function_calls() { | 609 | fn inserts_parens_for_function_calls() { |
604 | covers!(inserts_parens_for_function_calls); | 610 | mark::check!(inserts_parens_for_function_calls); |
605 | assert_debug_snapshot!( | 611 | assert_debug_snapshot!( |
606 | do_reference_completion( | 612 | do_reference_completion( |
607 | r" | 613 | r" |
@@ -986,7 +992,7 @@ mod tests { | |||
986 | 992 | ||
987 | #[test] | 993 | #[test] |
988 | fn inserts_angle_brackets_for_generics() { | 994 | fn inserts_angle_brackets_for_generics() { |
989 | covers!(inserts_angle_brackets_for_generics); | 995 | mark::check!(inserts_angle_brackets_for_generics); |
990 | assert_debug_snapshot!( | 996 | assert_debug_snapshot!( |
991 | do_reference_completion( | 997 | do_reference_completion( |
992 | r" | 998 | r" |
@@ -1109,7 +1115,7 @@ mod tests { | |||
1109 | 1115 | ||
1110 | #[test] | 1116 | #[test] |
1111 | fn dont_insert_macro_call_parens_unncessary() { | 1117 | fn dont_insert_macro_call_parens_unncessary() { |
1112 | covers!(dont_insert_macro_call_parens_unncessary); | 1118 | mark::check!(dont_insert_macro_call_parens_unncessary); |
1113 | assert_debug_snapshot!( | 1119 | assert_debug_snapshot!( |
1114 | do_reference_completion( | 1120 | do_reference_completion( |
1115 | r" | 1121 | r" |
@@ -1175,7 +1181,7 @@ mod tests { | |||
1175 | 1181 | ||
1176 | #[test] | 1182 | #[test] |
1177 | fn test_struct_field_completion_in_func_call() { | 1183 | fn test_struct_field_completion_in_func_call() { |
1178 | covers!(test_struct_field_completion_in_func_call); | 1184 | mark::check!(test_struct_field_completion_in_func_call); |
1179 | assert_debug_snapshot!( | 1185 | assert_debug_snapshot!( |
1180 | do_reference_completion( | 1186 | do_reference_completion( |
1181 | r" | 1187 | r" |
@@ -1265,7 +1271,7 @@ mod tests { | |||
1265 | 1271 | ||
1266 | #[test] | 1272 | #[test] |
1267 | fn test_struct_field_completion_in_record_lit() { | 1273 | fn test_struct_field_completion_in_record_lit() { |
1268 | covers!(test_struct_field_completion_in_record_lit); | 1274 | mark::check!(test_struct_field_completion_in_record_lit); |
1269 | assert_debug_snapshot!( | 1275 | assert_debug_snapshot!( |
1270 | do_reference_completion( | 1276 | do_reference_completion( |
1271 | r" | 1277 | r" |
@@ -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 | } |