aboutsummaryrefslogtreecommitdiff
path: root/crates/completion/src/render/function.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/completion/src/render/function.rs')
-rw-r--r--crates/completion/src/render/function.rs69
1 files changed, 52 insertions, 17 deletions
diff --git a/crates/completion/src/render/function.rs b/crates/completion/src/render/function.rs
index 542383d7e..00e3eb203 100644
--- a/crates/completion/src/render/function.rs
+++ b/crates/completion/src/render/function.rs
@@ -2,6 +2,7 @@
2 2
3use hir::{HasSource, Type}; 3use hir::{HasSource, Type};
4use syntax::{ast::Fn, display::function_declaration}; 4use syntax::{ast::Fn, display::function_declaration};
5use test_utils::mark;
5 6
6use crate::{ 7use crate::{
7 item::{CompletionItem, CompletionItemKind, CompletionKind, ImportToAdd}, 8 item::{CompletionItem, CompletionItemKind, CompletionKind, ImportToAdd},
@@ -22,7 +23,7 @@ pub(crate) fn render_fn<'a>(
22struct FunctionRender<'a> { 23struct FunctionRender<'a> {
23 ctx: RenderContext<'a>, 24 ctx: RenderContext<'a>,
24 name: String, 25 name: String,
25 fn_: hir::Function, 26 func: hir::Function,
26 ast_node: Fn, 27 ast_node: Fn,
27} 28}
28 29
@@ -35,15 +36,15 @@ impl<'a> FunctionRender<'a> {
35 let name = local_name.unwrap_or_else(|| fn_.name(ctx.db()).to_string()); 36 let name = local_name.unwrap_or_else(|| fn_.name(ctx.db()).to_string());
36 let ast_node = fn_.source(ctx.db()).value; 37 let ast_node = fn_.source(ctx.db()).value;
37 38
38 FunctionRender { ctx, name, fn_, ast_node } 39 FunctionRender { ctx, name, func: fn_, ast_node }
39 } 40 }
40 41
41 fn render(self, import_to_add: Option<ImportToAdd>) -> CompletionItem { 42 fn render(self, import_to_add: Option<ImportToAdd>) -> CompletionItem {
42 let params = self.params(); 43 let params = self.params();
43 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), self.name.clone()) 44 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), self.name.clone())
44 .kind(self.kind()) 45 .kind(self.kind())
45 .set_documentation(self.ctx.docs(self.fn_)) 46 .set_documentation(self.ctx.docs(self.func))
46 .set_deprecated(self.ctx.is_deprecated(self.fn_)) 47 .set_deprecated(self.ctx.is_deprecated(self.func))
47 .detail(self.detail()) 48 .detail(self.detail())
48 .add_call_parens(self.ctx.completion, self.name, params) 49 .add_call_parens(self.ctx.completion, self.name, params)
49 .add_import(import_to_add) 50 .add_import(import_to_add)
@@ -67,27 +68,39 @@ impl<'a> FunctionRender<'a> {
67 } 68 }
68 69
69 fn params(&self) -> Params { 70 fn params(&self) -> Params {
70 let params_ty = self.fn_.params(self.ctx.db()); 71 let ast_params = match self.ast_node.param_list() {
71 let params = self 72 Some(it) => it,
72 .ast_node 73 None => return Params::Named(Vec::new()),
73 .param_list() 74 };
75
76 let mut params_pats = Vec::new();
77 let params_ty = if self.ctx.completion.dot_receiver.is_some() {
78 self.func.method_params(self.ctx.db()).unwrap_or_default()
79 } else {
80 if let Some(s) = ast_params.self_param() {
81 mark::hit!(parens_for_method_call_as_assoc_fn);
82 params_pats.push(Some(s.to_string()));
83 }
84 self.func.assoc_fn_params(self.ctx.db())
85 };
86 params_pats
87 .extend(ast_params.params().into_iter().map(|it| it.pat().map(|it| it.to_string())));
88
89 let params = params_pats
74 .into_iter() 90 .into_iter()
75 .flat_map(|it| it.params())
76 .zip(params_ty) 91 .zip(params_ty)
77 .flat_map(|(it, param_ty)| { 92 .flat_map(|(pat, param_ty)| {
78 if let Some(pat) = it.pat() { 93 let pat = pat?;
79 let name = pat.to_string(); 94 let name = pat.to_string();
80 let arg = name.trim_start_matches("mut ").trim_start_matches('_'); 95 let arg = name.trim_start_matches("mut ").trim_start_matches('_');
81 return Some(self.add_arg(arg, param_ty.ty())); 96 Some(self.add_arg(arg, param_ty.ty()))
82 }
83 None
84 }) 97 })
85 .collect(); 98 .collect();
86 Params::Named(params) 99 Params::Named(params)
87 } 100 }
88 101
89 fn kind(&self) -> CompletionItemKind { 102 fn kind(&self) -> CompletionItemKind {
90 if self.fn_.self_param(self.ctx.db()).is_some() { 103 if self.func.self_param(self.ctx.db()).is_some() {
91 CompletionItemKind::Method 104 CompletionItemKind::Method
92 } else { 105 } else {
93 CompletionItemKind::Function 106 CompletionItemKind::Function
@@ -173,6 +186,28 @@ fn bar(s: &S) {
173 } 186 }
174 187
175 #[test] 188 #[test]
189 fn parens_for_method_call_as_assoc_fn() {
190 mark::check!(parens_for_method_call_as_assoc_fn);
191 check_edit(
192 "foo",
193 r#"
194struct S;
195impl S {
196 fn foo(&self) {}
197}
198fn main() { S::f<|> }
199"#,
200 r#"
201struct S;
202impl S {
203 fn foo(&self) {}
204}
205fn main() { S::foo(${1:&self})$0 }
206"#,
207 );
208 }
209
210 #[test]
176 fn suppress_arg_snippets() { 211 fn suppress_arg_snippets() {
177 mark::check!(suppress_arg_snippets); 212 mark::check!(suppress_arg_snippets);
178 check_edit_with_config( 213 check_edit_with_config(