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 | |
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')
-rw-r--r-- | crates/completion/src/completions/qualified_path.rs | 40 | ||||
-rw-r--r-- | crates/completion/src/completions/trait_impl.rs | 2 | ||||
-rw-r--r-- | crates/completion/src/render/builder_ext.rs | 5 | ||||
-rw-r--r-- | crates/completion/src/render/function.rs | 69 | ||||
-rw-r--r-- | crates/hir/src/code_model.rs | 12 | ||||
-rw-r--r-- | crates/ide/src/references/rename.rs | 2 |
6 files changed, 87 insertions, 43 deletions
diff --git a/crates/completion/src/completions/qualified_path.rs b/crates/completion/src/completions/qualified_path.rs index d9387054d..bc23bea3f 100644 --- a/crates/completion/src/completions/qualified_path.rs +++ b/crates/completion/src/completions/qualified_path.rs | |||
@@ -353,10 +353,10 @@ impl S { | |||
353 | fn foo() { let _ = S::<|> } | 353 | fn foo() { let _ = S::<|> } |
354 | "#, | 354 | "#, |
355 | expect![[r#" | 355 | expect![[r#" |
356 | ct C const C: i32 = 42; | 356 | ct C const C: i32 = 42; |
357 | ta T type T = i32; | 357 | ta T type T = i32; |
358 | fn a() fn a() | 358 | fn a() fn a() |
359 | me b() fn b(&self) | 359 | me b(…) fn b(&self) |
360 | "#]], | 360 | "#]], |
361 | ); | 361 | ); |
362 | } | 362 | } |
@@ -503,14 +503,14 @@ trait Sub: Super { | |||
503 | fn foo<T: Sub>() { T::<|> } | 503 | fn foo<T: Sub>() { T::<|> } |
504 | "#, | 504 | "#, |
505 | expect![[r#" | 505 | expect![[r#" |
506 | ct C2 const C2: (); | 506 | ct C2 const C2: (); |
507 | ct CONST const CONST: u8; | 507 | ct CONST const CONST: u8; |
508 | ta SubTy type SubTy; | 508 | ta SubTy type SubTy; |
509 | ta Ty type Ty; | 509 | ta Ty type Ty; |
510 | fn func() fn func() | 510 | fn func() fn func() |
511 | me method() fn method(&self) | 511 | me method(…) fn method(&self) |
512 | fn subfunc() fn subfunc() | 512 | fn subfunc() fn subfunc() |
513 | me submethod() fn submethod(&self) | 513 | me submethod(…) fn submethod(&self) |
514 | "#]], | 514 | "#]], |
515 | ); | 515 | ); |
516 | } | 516 | } |
@@ -543,14 +543,14 @@ impl<T> Sub for Wrap<T> { | |||
543 | } | 543 | } |
544 | "#, | 544 | "#, |
545 | expect![[r#" | 545 | expect![[r#" |
546 | ct C2 const C2: () = (); | 546 | ct C2 const C2: () = (); |
547 | ct CONST const CONST: u8 = 0; | 547 | ct CONST const CONST: u8 = 0; |
548 | ta SubTy type SubTy; | 548 | ta SubTy type SubTy; |
549 | ta Ty type Ty; | 549 | ta Ty type Ty; |
550 | fn func() fn func() | 550 | fn func() fn func() |
551 | me method() fn method(&self) | 551 | me method(…) fn method(&self) |
552 | fn subfunc() fn subfunc() | 552 | fn subfunc() fn subfunc() |
553 | me submethod() fn submethod(&self) | 553 | me submethod(…) fn submethod(&self) |
554 | "#]], | 554 | "#]], |
555 | ); | 555 | ); |
556 | } | 556 | } |
diff --git a/crates/completion/src/completions/trait_impl.rs b/crates/completion/src/completions/trait_impl.rs index a14be9c73..e2fe44aff 100644 --- a/crates/completion/src/completions/trait_impl.rs +++ b/crates/completion/src/completions/trait_impl.rs | |||
@@ -139,7 +139,7 @@ fn add_function_impl( | |||
139 | ) { | 139 | ) { |
140 | let fn_name = func.name(ctx.db).to_string(); | 140 | let fn_name = func.name(ctx.db).to_string(); |
141 | 141 | ||
142 | let label = if func.params(ctx.db).is_empty() { | 142 | let label = if func.assoc_fn_params(ctx.db).is_empty() { |
143 | format!("fn {}()", fn_name) | 143 | format!("fn {}()", fn_name) |
144 | } else { | 144 | } else { |
145 | format!("fn {}(..)", fn_name) | 145 | format!("fn {}(..)", fn_name) |
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( |
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index f06b5cd9f..4500050f1 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs | |||
@@ -744,14 +744,13 @@ impl Function { | |||
744 | Some(SelfParam { func: self.id }) | 744 | Some(SelfParam { func: self.id }) |
745 | } | 745 | } |
746 | 746 | ||
747 | pub fn params(self, db: &dyn HirDatabase) -> Vec<Param> { | 747 | pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param> { |
748 | let resolver = self.id.resolver(db.upcast()); | 748 | let resolver = self.id.resolver(db.upcast()); |
749 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); | 749 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); |
750 | let environment = TraitEnvironment::lower(db, &resolver); | 750 | let environment = TraitEnvironment::lower(db, &resolver); |
751 | db.function_data(self.id) | 751 | db.function_data(self.id) |
752 | .params | 752 | .params |
753 | .iter() | 753 | .iter() |
754 | .skip(if self.self_param(db).is_some() { 1 } else { 0 }) | ||
755 | .map(|type_ref| { | 754 | .map(|type_ref| { |
756 | let ty = Type { | 755 | let ty = Type { |
757 | krate: self.id.lookup(db.upcast()).container.module(db.upcast()).krate, | 756 | krate: self.id.lookup(db.upcast()).container.module(db.upcast()).krate, |
@@ -764,6 +763,14 @@ impl Function { | |||
764 | }) | 763 | }) |
765 | .collect() | 764 | .collect() |
766 | } | 765 | } |
766 | pub fn method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param>> { | ||
767 | if self.self_param(db).is_none() { | ||
768 | return None; | ||
769 | } | ||
770 | let mut res = self.assoc_fn_params(db); | ||
771 | res.remove(0); | ||
772 | Some(res) | ||
773 | } | ||
767 | 774 | ||
768 | pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { | 775 | pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { |
769 | db.function_data(self.id).is_unsafe | 776 | db.function_data(self.id).is_unsafe |
@@ -799,6 +806,7 @@ impl From<Mutability> for Access { | |||
799 | } | 806 | } |
800 | } | 807 | } |
801 | 808 | ||
809 | #[derive(Debug)] | ||
802 | pub struct Param { | 810 | pub struct Param { |
803 | ty: Type, | 811 | ty: Type, |
804 | } | 812 | } |
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs index 731457696..64fe8bd65 100644 --- a/crates/ide/src/references/rename.rs +++ b/crates/ide/src/references/rename.rs | |||
@@ -241,7 +241,7 @@ fn rename_to_self( | |||
241 | return Err(RenameError("Method already has a self parameter".to_string())); | 241 | return Err(RenameError("Method already has a self parameter".to_string())); |
242 | } | 242 | } |
243 | 243 | ||
244 | let params = fn_def.params(sema.db); | 244 | let params = fn_def.assoc_fn_params(sema.db); |
245 | let first_param = | 245 | let first_param = |
246 | params.first().ok_or_else(|| RenameError("Method has no parameters".into()))?; | 246 | params.first().ok_or_else(|| RenameError("Method has no parameters".into()))?; |
247 | let first_param_ty = first_param.ty(); | 247 | let first_param_ty = first_param.ty(); |