aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2021-06-20 17:32:45 +0100
committerAleksey Kladov <[email protected]>2021-06-20 17:37:58 +0100
commit9a3eae8755f99f4cfb8c2abb0885ec500b946218 (patch)
tree040844f1a7cbd829586a883e292f3fa5f090e3cb /crates/ide_completion/src
parentf1097c2d26b68741612ecd3411fe41dc13fb005a (diff)
fix: don't add duplicate `&` during completion
Diffstat (limited to 'crates/ide_completion/src')
-rw-r--r--crates/ide_completion/src/context.rs65
-rw-r--r--crates/ide_completion/src/render.rs75
2 files changed, 72 insertions, 68 deletions
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index e49e434fa..7b76600df 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -385,14 +385,19 @@ impl<'a> CompletionContext<'a> {
385 (ty, name) 385 (ty, name)
386 }, 386 },
387 ast::ArgList(_it) => { 387 ast::ArgList(_it) => {
388 cov_mark::hit!(expected_type_fn_param_with_leading_char); 388 cov_mark::hit!(expected_type_fn_param);
389 cov_mark::hit!(expected_type_fn_param_without_leading_char);
390 ActiveParameter::at_token( 389 ActiveParameter::at_token(
391 &self.sema, 390 &self.sema,
392 self.token.clone(), 391 self.token.clone(),
393 ).map(|ap| { 392 ).map(|ap| {
394 let name = ap.ident().map(NameOrNameRef::Name); 393 let name = ap.ident().map(NameOrNameRef::Name);
395 (Some(ap.ty), name) 394 let ty = if has_ref(&self.token) {
395 cov_mark::hit!(expected_type_fn_param_ref);
396 ap.ty.remove_ref()
397 } else {
398 Some(ap.ty)
399 };
400 (ty, name)
396 }) 401 })
397 .unwrap_or((None, None)) 402 .unwrap_or((None, None))
398 }, 403 },
@@ -697,6 +702,19 @@ fn path_or_use_tree_qualifier(path: &ast::Path) -> Option<(ast::Path, bool)> {
697 use_tree.path().zip(Some(true)) 702 use_tree.path().zip(Some(true))
698} 703}
699 704
705fn has_ref(token: &SyntaxToken) -> bool {
706 let mut token = token.clone();
707 for skip in [WHITESPACE, IDENT, T![mut]] {
708 if token.kind() == skip {
709 token = match token.prev_token() {
710 Some(it) => it,
711 None => return false,
712 }
713 }
714 }
715 token.kind() == T![&]
716}
717
700#[cfg(test)] 718#[cfg(test)]
701mod tests { 719mod tests {
702 use expect_test::{expect, Expect}; 720 use expect_test::{expect, Expect};
@@ -769,14 +787,18 @@ fn foo() {
769 } 787 }
770 788
771 #[test] 789 #[test]
772 fn expected_type_fn_param_without_leading_char() { 790 fn expected_type_fn_param() {
773 cov_mark::check!(expected_type_fn_param_without_leading_char); 791 cov_mark::check!(expected_type_fn_param);
774 check_expected_type_and_name( 792 check_expected_type_and_name(
775 r#" 793 r#"
776fn foo() { 794fn foo() { bar($0); }
777 bar($0); 795fn bar(x: u32) {}
778} 796"#,
779 797 expect![[r#"ty: u32, name: x"#]],
798 );
799 check_expected_type_and_name(
800 r#"
801fn foo() { bar(c$0); }
780fn bar(x: u32) {} 802fn bar(x: u32) {}
781"#, 803"#,
782 expect![[r#"ty: u32, name: x"#]], 804 expect![[r#"ty: u32, name: x"#]],
@@ -784,18 +806,29 @@ fn bar(x: u32) {}
784 } 806 }
785 807
786 #[test] 808 #[test]
787 fn expected_type_fn_param_with_leading_char() { 809 fn expected_type_fn_param_ref() {
788 cov_mark::check!(expected_type_fn_param_with_leading_char); 810 cov_mark::check!(expected_type_fn_param_ref);
789 check_expected_type_and_name( 811 check_expected_type_and_name(
790 r#" 812 r#"
791fn foo() { 813fn foo() { bar(&$0); }
792 bar(c$0); 814fn bar(x: &u32) {}
793}
794
795fn bar(x: u32) {}
796"#, 815"#,
797 expect![[r#"ty: u32, name: x"#]], 816 expect![[r#"ty: u32, name: x"#]],
798 ); 817 );
818 check_expected_type_and_name(
819 r#"
820fn foo() { bar(&mut $0); }
821fn bar(x: &mut u32) {}
822"#,
823 expect![[r#"ty: u32, name: x"#]],
824 );
825 check_expected_type_and_name(
826 r#"
827fn foo() { bar(&c$0); }
828fn bar(x: &u32) {}
829 "#,
830 expect![[r#"ty: u32, name: x"#]],
831 );
799 } 832 }
800 833
801 #[test] 834 #[test]
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs
index 9bec03e17..1a9b6212a 100644
--- a/crates/ide_completion/src/render.rs
+++ b/crates/ide_completion/src/render.rs
@@ -1057,7 +1057,7 @@ fn f() {
1057 #[test] 1057 #[test]
1058 fn suggest_ref_mut() { 1058 fn suggest_ref_mut() {
1059 cov_mark::check!(suggest_ref); 1059 cov_mark::check!(suggest_ref);
1060 check( 1060 check_relevance(
1061 r#" 1061 r#"
1062struct S; 1062struct S;
1063fn foo(s: &mut S) {} 1063fn foo(s: &mut S) {}
@@ -1067,58 +1067,29 @@ fn main() {
1067} 1067}
1068 "#, 1068 "#,
1069 expect![[r#" 1069 expect![[r#"
1070 [ 1070 lc s [name+local]
1071 CompletionItem { 1071 lc &mut s [type+name+local]
1072 label: "S", 1072 st S []
1073 source_range: 70..70, 1073 fn main() []
1074 delete: 70..70, 1074 fn foo(…) []
1075 insert: "S",
1076 kind: SymbolKind(
1077 Struct,
1078 ),
1079 },
1080 CompletionItem {
1081 label: "foo(…)",
1082 source_range: 70..70,
1083 delete: 70..70,
1084 insert: "foo(${1:&mut s})$0",
1085 kind: SymbolKind(
1086 Function,
1087 ),
1088 lookup: "foo",
1089 detail: "fn(&mut S)",
1090 trigger_call_info: true,
1091 },
1092 CompletionItem {
1093 label: "main()",
1094 source_range: 70..70,
1095 delete: 70..70,
1096 insert: "main()$0",
1097 kind: SymbolKind(
1098 Function,
1099 ),
1100 lookup: "main",
1101 detail: "fn()",
1102 },
1103 CompletionItem {
1104 label: "s",
1105 source_range: 70..70,
1106 delete: 70..70,
1107 insert: "s",
1108 kind: SymbolKind(
1109 Local,
1110 ),
1111 detail: "S",
1112 relevance: CompletionRelevance {
1113 exact_name_match: true,
1114 type_match: None,
1115 is_local: true,
1116 },
1117 ref_match: "&mut ",
1118 },
1119 ]
1120 "#]], 1075 "#]],
1121 ) 1076 );
1077 check_relevance(
1078 r#"
1079struct S;
1080fn foo(s: &mut S) {}
1081fn main() {
1082 let mut s = S;
1083 foo(&mut $0);
1084}
1085 "#,
1086 expect![[r#"
1087 lc s [type+name+local]
1088 st S []
1089 fn main() []
1090 fn foo(…) []
1091 "#]],
1092 );
1122 } 1093 }
1123 1094
1124 #[test] 1095 #[test]