aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-12-01 11:29:25 +0000
committerGitHub <[email protected]>2020-12-01 11:29:25 +0000
commit75e037fcf75691a3a87d0cb37ea660dd7105ffba (patch)
tree0a08b79f8fb8f5da53e5d700d827d325cd326178
parent455a0cfda2121596deb13ca3f40a83c98b32863c (diff)
parent9d94ffad44f2b250e498f162cd498aed62877c8e (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]>
-rw-r--r--crates/completion/src/completions/qualified_path.rs40
-rw-r--r--crates/completion/src/completions/trait_impl.rs2
-rw-r--r--crates/completion/src/render/builder_ext.rs5
-rw-r--r--crates/completion/src/render/function.rs69
-rw-r--r--crates/hir/src/code_model.rs12
-rw-r--r--crates/ide/src/references/rename.rs2
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 {
353fn foo() { let _ = S::<|> } 353fn 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 {
503fn foo<T: Sub>() { T::<|> } 503fn 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
6use crate::{item::Builder, CompletionContext}; 6use crate::{item::Builder, CompletionContext};
7 7
8#[derive(Debug)]
8pub(super) enum Params { 9pub(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
26impl Builder { 27impl 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
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(
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)]
802pub struct Param { 810pub 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();