aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide/src')
-rw-r--r--crates/ide/src/completion/presentation.rs107
1 files changed, 105 insertions, 2 deletions
diff --git a/crates/ide/src/completion/presentation.rs b/crates/ide/src/completion/presentation.rs
index 24c507f9b..cfcb6dfa1 100644
--- a/crates/ide/src/completion/presentation.rs
+++ b/crates/ide/src/completion/presentation.rs
@@ -191,6 +191,22 @@ impl Completions {
191 func: hir::Function, 191 func: hir::Function,
192 local_name: Option<String>, 192 local_name: Option<String>,
193 ) { 193 ) {
194 fn add_arg(arg: &str, ty: &Type, ctx: &CompletionContext) -> String {
195 let mut prefix = "";
196 if let Some(derefed_ty) = ty.remove_ref() {
197 ctx.scope.process_all_names(&mut |name, scope| {
198 if prefix != "" {
199 return;
200 }
201 if let ScopeDef::Local(local) = scope {
202 if name.to_string() == arg && local.can_unify(derefed_ty.clone(), ctx.db) {
203 prefix = if ty.is_mutable_reference() { "&mut " } else { "&" };
204 }
205 }
206 });
207 }
208 prefix.to_string() + arg
209 };
194 let name = local_name.unwrap_or_else(|| func.name(ctx.db).to_string()); 210 let name = local_name.unwrap_or_else(|| func.name(ctx.db).to_string());
195 let ast_node = func.source(ctx.db).value; 211 let ast_node = func.source(ctx.db).value;
196 212
@@ -205,12 +221,20 @@ impl Completions {
205 .set_deprecated(is_deprecated(func, ctx.db)) 221 .set_deprecated(is_deprecated(func, ctx.db))
206 .detail(function_declaration(&ast_node)); 222 .detail(function_declaration(&ast_node));
207 223
224 let params_ty = func.params(ctx.db);
208 let params = ast_node 225 let params = ast_node
209 .param_list() 226 .param_list()
210 .into_iter() 227 .into_iter()
211 .flat_map(|it| it.params()) 228 .flat_map(|it| it.params())
212 .flat_map(|it| it.pat()) 229 .zip(params_ty)
213 .map(|pat| pat.to_string().trim_start_matches('_').into()) 230 .flat_map(|(it, param_ty)| {
231 if let Some(pat) = it.pat() {
232 let name = pat.to_string();
233 let arg = name.trim_start_matches('_');
234 return Some(add_arg(arg, &param_ty, ctx));
235 }
236 None
237 })
214 .collect(); 238 .collect();
215 239
216 builder = builder.add_call_parens(ctx, name, Params::Named(params)); 240 builder = builder.add_call_parens(ctx, name, Params::Named(params));
@@ -864,6 +888,85 @@ fn main() { foo(${1:foo}, ${2:bar}, ${3:ho_ge_})$0 }
864 } 888 }
865 889
866 #[test] 890 #[test]
891 fn insert_ref_when_matching_local_in_scope() {
892 check_edit(
893 "ref_arg",
894 r#"
895struct Foo {}
896fn ref_arg(x: &Foo) {}
897fn main() {
898 let x = Foo {};
899 ref_ar<|>
900}
901"#,
902 r#"
903struct Foo {}
904fn ref_arg(x: &Foo) {}
905fn main() {
906 let x = Foo {};
907 ref_arg(${1:&x})$0
908}
909"#,
910 );
911 }
912
913 #[test]
914 fn insert_mut_ref_when_matching_local_in_scope() {
915 check_edit(
916 "ref_arg",
917 r#"
918struct Foo {}
919fn ref_arg(x: &mut Foo) {}
920fn main() {
921 let x = Foo {};
922 ref_ar<|>
923}
924"#,
925 r#"
926struct Foo {}
927fn ref_arg(x: &mut Foo) {}
928fn main() {
929 let x = Foo {};
930 ref_arg(${1:&mut x})$0
931}
932"#,
933 );
934 }
935
936 #[test]
937 fn insert_ref_when_matching_local_in_scope_for_method() {
938 check_edit(
939 "apply_foo",
940 r#"
941struct Foo {}
942struct Bar {}
943impl Bar {
944 fn apply_foo(&self, x: &Foo) {}
945}
946
947fn main() {
948 let x = Foo {};
949 let y = Bar {};
950 y.<|>
951}
952"#,
953 r#"
954struct Foo {}
955struct Bar {}
956impl Bar {
957 fn apply_foo(&self, x: &Foo) {}
958}
959
960fn main() {
961 let x = Foo {};
962 let y = Bar {};
963 y.apply_foo(${1:&x})$0
964}
965"#,
966 );
967 }
968
969 #[test]
867 fn inserts_parens_for_tuple_enums() { 970 fn inserts_parens_for_tuple_enums() {
868 mark::check!(inserts_parens_for_tuple_enums); 971 mark::check!(inserts_parens_for_tuple_enums);
869 check_edit( 972 check_edit(