diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-12-01 11:29:25 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-12-01 11:29:25 +0000 |
commit | 75e037fcf75691a3a87d0cb37ea660dd7105ffba (patch) | |
tree | 0a08b79f8fb8f5da53e5d700d827d325cd326178 /crates/completion/src/render | |
parent | 455a0cfda2121596deb13ca3f40a83c98b32863c (diff) | |
parent | 9d94ffad44f2b250e498f162cd498aed62877c8e (diff) |
Merge #6688
6688: Place cursor correctly when completing assoc fns with self r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/completion/src/render')
-rw-r--r-- | crates/completion/src/render/builder_ext.rs | 5 | ||||
-rw-r--r-- | crates/completion/src/render/function.rs | 69 |
2 files changed, 55 insertions, 19 deletions
diff --git a/crates/completion/src/render/builder_ext.rs b/crates/completion/src/render/builder_ext.rs index 37b0d0459..ce8718bd5 100644 --- a/crates/completion/src/render/builder_ext.rs +++ b/crates/completion/src/render/builder_ext.rs | |||
@@ -5,6 +5,7 @@ use test_utils::mark; | |||
5 | 5 | ||
6 | use crate::{item::Builder, CompletionContext}; | 6 | use crate::{item::Builder, CompletionContext}; |
7 | 7 | ||
8 | #[derive(Debug)] | ||
8 | pub(super) enum Params { | 9 | pub(super) enum Params { |
9 | Named(Vec<String>), | 10 | Named(Vec<String>), |
10 | Anonymous(usize), | 11 | Anonymous(usize), |
@@ -24,7 +25,7 @@ impl Params { | |||
24 | } | 25 | } |
25 | 26 | ||
26 | impl Builder { | 27 | impl Builder { |
27 | pub(super) fn should_add_parems(&self, ctx: &CompletionContext) -> bool { | 28 | fn should_add_parens(&self, ctx: &CompletionContext) -> bool { |
28 | if !ctx.config.add_call_parenthesis { | 29 | if !ctx.config.add_call_parenthesis { |
29 | return false; | 30 | return false; |
30 | } | 31 | } |
@@ -58,7 +59,7 @@ impl Builder { | |||
58 | name: String, | 59 | name: String, |
59 | params: Params, | 60 | params: Params, |
60 | ) -> Builder { | 61 | ) -> Builder { |
61 | if !self.should_add_parems(ctx) { | 62 | if !self.should_add_parens(ctx) { |
62 | return self; | 63 | return self; |
63 | } | 64 | } |
64 | 65 | ||
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 | ||
3 | use hir::{HasSource, Type}; | 3 | use hir::{HasSource, Type}; |
4 | use syntax::{ast::Fn, display::function_declaration}; | 4 | use syntax::{ast::Fn, display::function_declaration}; |
5 | use test_utils::mark; | ||
5 | 6 | ||
6 | use crate::{ | 7 | use crate::{ |
7 | item::{CompletionItem, CompletionItemKind, CompletionKind, ImportToAdd}, | 8 | item::{CompletionItem, CompletionItemKind, CompletionKind, ImportToAdd}, |
@@ -22,7 +23,7 @@ pub(crate) fn render_fn<'a>( | |||
22 | struct FunctionRender<'a> { | 23 | struct 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#" | ||
194 | struct S; | ||
195 | impl S { | ||
196 | fn foo(&self) {} | ||
197 | } | ||
198 | fn main() { S::f<|> } | ||
199 | "#, | ||
200 | r#" | ||
201 | struct S; | ||
202 | impl S { | ||
203 | fn foo(&self) {} | ||
204 | } | ||
205 | fn 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( |