From c6ddb907144688ae77a6de3666159feef53638e1 Mon Sep 17 00:00:00 2001 From: adamrk Date: Sat, 22 Aug 2020 20:11:37 +0200 Subject: Add references to fn args during completion --- crates/ide/src/completion/presentation.rs | 107 +++++++++++++++++++++++++++++- 1 file changed, 105 insertions(+), 2 deletions(-) (limited to 'crates/ide/src') 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 { func: hir::Function, local_name: Option, ) { + fn add_arg(arg: &str, ty: &Type, ctx: &CompletionContext) -> String { + let mut prefix = ""; + if let Some(derefed_ty) = ty.remove_ref() { + ctx.scope.process_all_names(&mut |name, scope| { + if prefix != "" { + return; + } + if let ScopeDef::Local(local) = scope { + if name.to_string() == arg && local.can_unify(derefed_ty.clone(), ctx.db) { + prefix = if ty.is_mutable_reference() { "&mut " } else { "&" }; + } + } + }); + } + prefix.to_string() + arg + }; let name = local_name.unwrap_or_else(|| func.name(ctx.db).to_string()); let ast_node = func.source(ctx.db).value; @@ -205,12 +221,20 @@ impl Completions { .set_deprecated(is_deprecated(func, ctx.db)) .detail(function_declaration(&ast_node)); + let params_ty = func.params(ctx.db); let params = ast_node .param_list() .into_iter() .flat_map(|it| it.params()) - .flat_map(|it| it.pat()) - .map(|pat| pat.to_string().trim_start_matches('_').into()) + .zip(params_ty) + .flat_map(|(it, param_ty)| { + if let Some(pat) = it.pat() { + let name = pat.to_string(); + let arg = name.trim_start_matches('_'); + return Some(add_arg(arg, ¶m_ty, ctx)); + } + None + }) .collect(); builder = builder.add_call_parens(ctx, name, Params::Named(params)); @@ -863,6 +887,85 @@ fn main() { foo(${1:foo}, ${2:bar}, ${3:ho_ge_})$0 } ); } + #[test] + fn insert_ref_when_matching_local_in_scope() { + check_edit( + "ref_arg", + r#" +struct Foo {} +fn ref_arg(x: &Foo) {} +fn main() { + let x = Foo {}; + ref_ar<|> +} +"#, + r#" +struct Foo {} +fn ref_arg(x: &Foo) {} +fn main() { + let x = Foo {}; + ref_arg(${1:&x})$0 +} +"#, + ); + } + + #[test] + fn insert_mut_ref_when_matching_local_in_scope() { + check_edit( + "ref_arg", + r#" +struct Foo {} +fn ref_arg(x: &mut Foo) {} +fn main() { + let x = Foo {}; + ref_ar<|> +} +"#, + r#" +struct Foo {} +fn ref_arg(x: &mut Foo) {} +fn main() { + let x = Foo {}; + ref_arg(${1:&mut x})$0 +} +"#, + ); + } + + #[test] + fn insert_ref_when_matching_local_in_scope_for_method() { + check_edit( + "apply_foo", + r#" +struct Foo {} +struct Bar {} +impl Bar { + fn apply_foo(&self, x: &Foo) {} +} + +fn main() { + let x = Foo {}; + let y = Bar {}; + y.<|> +} +"#, + r#" +struct Foo {} +struct Bar {} +impl Bar { + fn apply_foo(&self, x: &Foo) {} +} + +fn main() { + let x = Foo {}; + let y = Bar {}; + y.apply_foo(${1:&x})$0 +} +"#, + ); + } + #[test] fn inserts_parens_for_tuple_enums() { mark::check!(inserts_parens_for_tuple_enums); -- cgit v1.2.3 From 04fc937700105951442a9b6fa30591fb48a1e879 Mon Sep 17 00:00:00 2001 From: adamrk Date: Tue, 1 Sep 2020 22:13:12 +0200 Subject: Add back Param struct --- crates/ide/src/completion/presentation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ide/src') diff --git a/crates/ide/src/completion/presentation.rs b/crates/ide/src/completion/presentation.rs index cfcb6dfa1..0c29d0be2 100644 --- a/crates/ide/src/completion/presentation.rs +++ b/crates/ide/src/completion/presentation.rs @@ -231,7 +231,7 @@ impl Completions { if let Some(pat) = it.pat() { let name = pat.to_string(); let arg = name.trim_start_matches('_'); - return Some(add_arg(arg, ¶m_ty, ctx)); + return Some(add_arg(arg, param_ty.ty(), ctx)); } None }) -- cgit v1.2.3 From d9bb86ad7dfd17543e6e1c9ef184337f828b1027 Mon Sep 17 00:00:00 2001 From: adamrk Date: Wed, 2 Sep 2020 20:38:08 +0200 Subject: Collect locals in context --- crates/ide/src/completion/completion_context.rs | 10 +++++++++- crates/ide/src/completion/presentation.rs | 17 ++++++----------- 2 files changed, 15 insertions(+), 12 deletions(-) (limited to 'crates/ide/src') diff --git a/crates/ide/src/completion/completion_context.rs b/crates/ide/src/completion/completion_context.rs index 47355d5dc..3ef1b97cf 100644 --- a/crates/ide/src/completion/completion_context.rs +++ b/crates/ide/src/completion/completion_context.rs @@ -1,7 +1,7 @@ //! FIXME: write short doc here use base_db::SourceDatabase; -use hir::{Semantics, SemanticsScope, Type}; +use hir::{Local, ScopeDef, Semantics, SemanticsScope, Type}; use ide_db::RootDatabase; use syntax::{ algo::{find_covering_element, find_node_at_offset}, @@ -90,6 +90,7 @@ pub(crate) struct CompletionContext<'a> { pub(super) impl_as_prev_sibling: bool, pub(super) is_match_arm: bool, pub(super) has_item_list_or_source_file_parent: bool, + pub(super) locals: Vec<(String, Local)>, } impl<'a> CompletionContext<'a> { @@ -118,6 +119,12 @@ impl<'a> CompletionContext<'a> { original_file.syntax().token_at_offset(position.offset).left_biased()?; let token = sema.descend_into_macros(original_token.clone()); let scope = sema.scope_at_offset(&token.parent(), position.offset); + let mut locals = vec![]; + scope.process_all_names(&mut |name, scope| { + if let ScopeDef::Local(local) = scope { + locals.push((name.to_string(), local)); + } + }); let mut ctx = CompletionContext { sema, scope, @@ -165,6 +172,7 @@ impl<'a> CompletionContext<'a> { if_is_prev: false, is_match_arm: false, has_item_list_or_source_file_parent: false, + locals, }; let mut original_file = original_file.syntax().clone(); diff --git a/crates/ide/src/completion/presentation.rs b/crates/ide/src/completion/presentation.rs index 0c29d0be2..059fdfdc9 100644 --- a/crates/ide/src/completion/presentation.rs +++ b/crates/ide/src/completion/presentation.rs @@ -192,20 +192,15 @@ impl Completions { local_name: Option, ) { fn add_arg(arg: &str, ty: &Type, ctx: &CompletionContext) -> String { - let mut prefix = ""; if let Some(derefed_ty) = ty.remove_ref() { - ctx.scope.process_all_names(&mut |name, scope| { - if prefix != "" { - return; + for (name, local) in ctx.locals.iter() { + if name == arg && local.can_unify(derefed_ty.clone(), ctx.db) { + return (if ty.is_mutable_reference() { "&mut " } else { "&" }).to_string() + + &arg.to_string(); } - if let ScopeDef::Local(local) = scope { - if name.to_string() == arg && local.can_unify(derefed_ty.clone(), ctx.db) { - prefix = if ty.is_mutable_reference() { "&mut " } else { "&" }; - } - } - }); + } } - prefix.to_string() + arg + arg.to_string() }; let name = local_name.unwrap_or_else(|| func.name(ctx.db).to_string()); let ast_node = func.source(ctx.db).value; -- cgit v1.2.3 From e11cd8fe35fbb4fcaf7859f4cef2dbd94ff7d230 Mon Sep 17 00:00:00 2001 From: adamrk Date: Wed, 2 Sep 2020 22:33:54 +0200 Subject: Remove exposing unification --- crates/ide/src/completion/presentation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ide/src') diff --git a/crates/ide/src/completion/presentation.rs b/crates/ide/src/completion/presentation.rs index 059fdfdc9..c7d460465 100644 --- a/crates/ide/src/completion/presentation.rs +++ b/crates/ide/src/completion/presentation.rs @@ -194,7 +194,7 @@ impl Completions { fn add_arg(arg: &str, ty: &Type, ctx: &CompletionContext) -> String { if let Some(derefed_ty) = ty.remove_ref() { for (name, local) in ctx.locals.iter() { - if name == arg && local.can_unify(derefed_ty.clone(), ctx.db) { + if name == arg && local.ty(ctx.db) == derefed_ty { return (if ty.is_mutable_reference() { "&mut " } else { "&" }).to_string() + &arg.to_string(); } -- cgit v1.2.3 From 66658f1168321e1ba3e6aae3f0c038308f0771d7 Mon Sep 17 00:00:00 2001 From: adamrk Date: Wed, 2 Sep 2020 22:49:21 +0200 Subject: Trim mut keyword in fn completion --- crates/ide/src/completion/presentation.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'crates/ide/src') diff --git a/crates/ide/src/completion/presentation.rs b/crates/ide/src/completion/presentation.rs index c7d460465..987cbfa7a 100644 --- a/crates/ide/src/completion/presentation.rs +++ b/crates/ide/src/completion/presentation.rs @@ -225,7 +225,7 @@ impl Completions { .flat_map(|(it, param_ty)| { if let Some(pat) = it.pat() { let name = pat.to_string(); - let arg = name.trim_start_matches('_'); + let arg = name.trim_start_matches("mut ").trim_start_matches('_'); return Some(add_arg(arg, param_ty.ty(), ctx)); } None @@ -961,6 +961,27 @@ fn main() { ); } + #[test] + fn trim_mut_keyword_in_func_completion() { + check_edit( + "take_mutably", + r#" +fn take_mutably(mut x: &i32) {} + +fn main() { + take_m<|> +} +"#, + r#" +fn take_mutably(mut x: &i32) {} + +fn main() { + take_mutably(${1:x})$0 +} +"#, + ); + } + #[test] fn inserts_parens_for_tuple_enums() { mark::check!(inserts_parens_for_tuple_enums); -- cgit v1.2.3