diff options
Diffstat (limited to 'crates/ide/src')
-rw-r--r-- | crates/ide/src/completion/presentation.rs | 107 |
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, ¶m_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#" | ||
895 | struct Foo {} | ||
896 | fn ref_arg(x: &Foo) {} | ||
897 | fn main() { | ||
898 | let x = Foo {}; | ||
899 | ref_ar<|> | ||
900 | } | ||
901 | "#, | ||
902 | r#" | ||
903 | struct Foo {} | ||
904 | fn ref_arg(x: &Foo) {} | ||
905 | fn 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#" | ||
918 | struct Foo {} | ||
919 | fn ref_arg(x: &mut Foo) {} | ||
920 | fn main() { | ||
921 | let x = Foo {}; | ||
922 | ref_ar<|> | ||
923 | } | ||
924 | "#, | ||
925 | r#" | ||
926 | struct Foo {} | ||
927 | fn ref_arg(x: &mut Foo) {} | ||
928 | fn 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#" | ||
941 | struct Foo {} | ||
942 | struct Bar {} | ||
943 | impl Bar { | ||
944 | fn apply_foo(&self, x: &Foo) {} | ||
945 | } | ||
946 | |||
947 | fn main() { | ||
948 | let x = Foo {}; | ||
949 | let y = Bar {}; | ||
950 | y.<|> | ||
951 | } | ||
952 | "#, | ||
953 | r#" | ||
954 | struct Foo {} | ||
955 | struct Bar {} | ||
956 | impl Bar { | ||
957 | fn apply_foo(&self, x: &Foo) {} | ||
958 | } | ||
959 | |||
960 | fn 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( |