From 23ffda1a97726ccdb70e43910ae4363f3e5b8448 Mon Sep 17 00:00:00 2001 From: vxpm Date: Sun, 3 Sep 2023 22:42:56 -0300 Subject: [PATCH 1/5] full function signatures option --- crates/ide-completion/src/config.rs | 1 + crates/ide-completion/src/render/function.rs | 8 ++++++-- crates/rust-analyzer/src/config.rs | 3 +++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/crates/ide-completion/src/config.rs b/crates/ide-completion/src/config.rs index 8f6a97e1e09..3d025f284bb 100644 --- a/crates/ide-completion/src/config.rs +++ b/crates/ide-completion/src/config.rs @@ -14,6 +14,7 @@ pub struct CompletionConfig { pub enable_imports_on_the_fly: bool, pub enable_self_on_the_fly: bool, pub enable_private_editable: bool, + pub full_function_signatures: bool, pub callable: Option, pub snippet_cap: Option, pub insert_use: InsertUseConfig, diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs index 8afce8db5ea..1672826f330 100644 --- a/crates/ide-completion/src/render/function.rs +++ b/crates/ide-completion/src/render/function.rs @@ -100,7 +100,7 @@ fn render( item.set_documentation(ctx.docs(func)) .set_deprecated(ctx.is_deprecated(func) || ctx.is_deprecated_assoc_item(func)) - .detail(detail(db, func)) + .detail(detail(db, func, ctx.completion.config.full_function_signatures)) .lookup_by(name.unescaped().to_smol_str()); match ctx.completion.config.snippet_cap { @@ -239,7 +239,11 @@ fn ref_of_param(ctx: &CompletionContext<'_>, arg: &str, ty: &hir::Type) -> &'sta "" } -fn detail(db: &dyn HirDatabase, func: hir::Function) -> String { +fn detail(db: &dyn HirDatabase, func: hir::Function, full_function_signature: bool) -> String { + if full_function_signature { + return format!("{}", func.display(db)).replace("\n", " "); + } + let mut ret_ty = func.ret_type(db); let mut detail = String::new(); diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index ea3a21241cb..07c6457b9c7 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -215,6 +215,8 @@ struct ConfigData { completion_postfix_enable: bool = "true", /// Enables completions of private items and fields that are defined in the current workspace even if they are not visible at the current position. completion_privateEditable_enable: bool = "false", + /// Whether to show full function/method signatures in completion docs. + completion_fullFunctionSignatures_enable: bool = "false", /// Custom completion snippets. // NOTE: Keep this list in sync with the feature docs of user snippets. completion_snippets_custom: FxHashMap = r#"{ @@ -1444,6 +1446,7 @@ pub fn completion(&self) -> CompletionConfig { && completion_item_edit_resolve(&self.caps), enable_self_on_the_fly: self.data.completion_autoself_enable, enable_private_editable: self.data.completion_privateEditable_enable, + full_function_signatures: self.data.completion_fullFunctionSignatures_enable, callable: match self.data.completion_callable_snippets { CallableCompletionDef::FillArguments => Some(CallableSnippets::FillArguments), CallableCompletionDef::AddParentheses => Some(CallableSnippets::AddParentheses), From 6afa5b0ba28c46905c0d0ac3022d4e1af0f1de36 Mon Sep 17 00:00:00 2001 From: vxpm Date: Sun, 3 Sep 2023 23:41:13 -0300 Subject: [PATCH 2/5] better handling of spaces & newlines --- crates/ide-completion/src/render/function.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs index 1672826f330..dd7de72190d 100644 --- a/crates/ide-completion/src/render/function.rs +++ b/crates/ide-completion/src/render/function.rs @@ -241,7 +241,18 @@ fn ref_of_param(ctx: &CompletionContext<'_>, arg: &str, ty: &hir::Type) -> &'sta fn detail(db: &dyn HirDatabase, func: hir::Function, full_function_signature: bool) -> String { if full_function_signature { - return format!("{}", func.display(db)).replace("\n", " "); + let signature = format!("{}", func.display(db)); + let mut singleline = String::with_capacity(signature.len()); + + for segment in signature.split_whitespace() { + if !singleline.is_empty() { + singleline.push(' '); + } + + singleline.push_str(segment); + } + + return singleline; } let mut ret_ty = func.ret_type(db); From 6b487ed4be81e723e0ed2035f79b27d9efb93b8a Mon Sep 17 00:00:00 2001 From: vxpm Date: Mon, 4 Sep 2023 00:02:08 -0300 Subject: [PATCH 3/5] fix & run tests --- crates/ide-completion/src/tests.rs | 1 + crates/rust-analyzer/src/config.rs | 4 ++-- crates/rust-analyzer/src/integrated_benchmarks.rs | 2 ++ docs/user/generated_config.adoc | 5 +++++ editors/code/package.json | 5 +++++ 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/crates/ide-completion/src/tests.rs b/crates/ide-completion/src/tests.rs index 2464e8d5f81..284bdd8af21 100644 --- a/crates/ide-completion/src/tests.rs +++ b/crates/ide-completion/src/tests.rs @@ -64,6 +64,7 @@ union Union { field: i32 } enable_imports_on_the_fly: true, enable_self_on_the_fly: true, enable_private_editable: false, + full_function_signatures: false, callable: Some(CallableSnippets::FillArguments), snippet_cap: SnippetCap::new(true), prefer_no_std: false, diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 07c6457b9c7..9382f4ea19e 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -209,14 +209,14 @@ struct ConfigData { completion_autoself_enable: bool = "true", /// Whether to add parenthesis and argument snippets when completing function. completion_callable_snippets: CallableCompletionDef = "\"fill_arguments\"", + /// Whether to show full function/method signatures in completion docs. + completion_fullFunctionSignatures_enable: bool = "false", /// Maximum number of completions to return. If `None`, the limit is infinite. completion_limit: Option = "null", /// Whether to show postfix snippets like `dbg`, `if`, `not`, etc. completion_postfix_enable: bool = "true", /// Enables completions of private items and fields that are defined in the current workspace even if they are not visible at the current position. completion_privateEditable_enable: bool = "false", - /// Whether to show full function/method signatures in completion docs. - completion_fullFunctionSignatures_enable: bool = "false", /// Custom completion snippets. // NOTE: Keep this list in sync with the feature docs of user snippets. completion_snippets_custom: FxHashMap = r#"{ diff --git a/crates/rust-analyzer/src/integrated_benchmarks.rs b/crates/rust-analyzer/src/integrated_benchmarks.rs index 5a11012b93c..2c402552919 100644 --- a/crates/rust-analyzer/src/integrated_benchmarks.rs +++ b/crates/rust-analyzer/src/integrated_benchmarks.rs @@ -134,6 +134,7 @@ fn integrated_completion_benchmark() { enable_imports_on_the_fly: true, enable_self_on_the_fly: true, enable_private_editable: true, + full_function_signatures: false, callable: Some(CallableSnippets::FillArguments), snippet_cap: SnippetCap::new(true), insert_use: InsertUseConfig { @@ -173,6 +174,7 @@ fn integrated_completion_benchmark() { enable_imports_on_the_fly: true, enable_self_on_the_fly: true, enable_private_editable: true, + full_function_signatures: false, callable: Some(CallableSnippets::FillArguments), snippet_cap: SnippetCap::new(true), insert_use: InsertUseConfig { diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 71feed0f72c..cf549565fe1 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -244,6 +244,11 @@ with `self` prefixed to them when inside a method. -- Whether to add parenthesis and argument snippets when completing function. -- +[[rust-analyzer.completion.fullFunctionSignatures.enable]]rust-analyzer.completion.fullFunctionSignatures.enable (default: `false`):: ++ +-- +Whether to show full function/method signatures in completion docs. +-- [[rust-analyzer.completion.limit]]rust-analyzer.completion.limit (default: `null`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index 233e7bf44b1..e075e227625 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -799,6 +799,11 @@ "Do no snippet completions for callables." ] }, + "rust-analyzer.completion.fullFunctionSignatures.enable": { + "markdownDescription": "Whether to show full function/method signatures in completion docs.", + "default": false, + "type": "boolean" + }, "rust-analyzer.completion.limit": { "markdownDescription": "Maximum number of completions to return. If `None`, the limit is infinite.", "default": null, From 9f3d627681e069ea313076ce65cbd28a8dfe0974 Mon Sep 17 00:00:00 2001 From: vxpm Date: Sat, 23 Sep 2023 19:39:42 -0300 Subject: [PATCH 4/5] add tests for full signatures --- crates/ide-completion/src/tests/special.rs | 73 +++++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/crates/ide-completion/src/tests/special.rs b/crates/ide-completion/src/tests/special.rs index e80a289049f..83888e08f1c 100644 --- a/crates/ide-completion/src/tests/special.rs +++ b/crates/ide-completion/src/tests/special.rs @@ -2,10 +2,15 @@ use expect_test::{expect, Expect}; -use crate::tests::{ - check_edit, completion_list, completion_list_no_kw, completion_list_with_trigger_character, +use crate::{ + tests::{ + check_edit, completion_list, completion_list_no_kw, completion_list_with_trigger_character, + }, + CompletionItemKind, }; +use super::{do_completion_with_config, TEST_CONFIG}; + fn check_no_kw(ra_fixture: &str, expect: Expect) { let actual = completion_list_no_kw(ra_fixture); expect.assert_eq(&actual) @@ -1303,3 +1308,67 @@ struct Foo(x: &'x mut T) -> u8 where T: Clone, { 0u8 } +fn main() { fo$0 } +"#, + CompletionItemKind::SymbolKind(ide_db::SymbolKind::Function), + expect!("fn(&mut T) -> u8"), + expect!("pub fn foo<'x, T>(x: &'x mut T) -> u8 where T: Clone,"), + ); + + check_signatures( + r#" +struct Foo; +struct Bar; +impl Bar { + pub const fn baz(x: Foo) -> ! { loop {} }; +} + +fn main() { Bar::b$0 } +"#, + CompletionItemKind::SymbolKind(ide_db::SymbolKind::Function), + expect!("const fn(Foo) -> !"), + expect!("pub const fn baz(x: Foo) -> !"), + ); + + check_signatures( + r#" +struct Foo; +struct Bar; +impl Bar { + pub const fn baz<'foo>(&'foo mut self, x: &'foo Foo) -> ! { loop {} }; +} + +fn main() { + let mut bar = Bar; + bar.b$0 +} +"#, + CompletionItemKind::Method, + expect!("const fn(&'foo mut self, &Foo) -> !"), + expect!("pub const fn baz<'foo>(&'foo mut self, x: &'foo Foo) -> !"), + ); +} From 10fae6282070945531853901cc19155f59758bbc Mon Sep 17 00:00:00 2001 From: vxpm Date: Sat, 23 Sep 2023 19:43:19 -0300 Subject: [PATCH 5/5] split detail function --- crates/ide-completion/src/render/function.rs | 39 +++++++++++--------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs index dd7de72190d..dfae715afe3 100644 --- a/crates/ide-completion/src/render/function.rs +++ b/crates/ide-completion/src/render/function.rs @@ -98,9 +98,14 @@ fn render( _ => (), } + let detail = if ctx.completion.config.full_function_signatures { + detail_full(db, func) + } else { + detail(db, func) + }; item.set_documentation(ctx.docs(func)) .set_deprecated(ctx.is_deprecated(func) || ctx.is_deprecated_assoc_item(func)) - .detail(detail(db, func, ctx.completion.config.full_function_signatures)) + .detail(detail) .lookup_by(name.unescaped().to_smol_str()); match ctx.completion.config.snippet_cap { @@ -239,22 +244,7 @@ fn ref_of_param(ctx: &CompletionContext<'_>, arg: &str, ty: &hir::Type) -> &'sta "" } -fn detail(db: &dyn HirDatabase, func: hir::Function, full_function_signature: bool) -> String { - if full_function_signature { - let signature = format!("{}", func.display(db)); - let mut singleline = String::with_capacity(signature.len()); - - for segment in signature.split_whitespace() { - if !singleline.is_empty() { - singleline.push(' '); - } - - singleline.push_str(segment); - } - - return singleline; - } - +fn detail(db: &dyn HirDatabase, func: hir::Function) -> String { let mut ret_ty = func.ret_type(db); let mut detail = String::new(); @@ -278,6 +268,21 @@ fn detail(db: &dyn HirDatabase, func: hir::Function, full_function_signature: bo detail } +fn detail_full(db: &dyn HirDatabase, func: hir::Function) -> String { + let signature = format!("{}", func.display(db)); + let mut detail = String::with_capacity(signature.len()); + + for segment in signature.split_whitespace() { + if !detail.is_empty() { + detail.push(' '); + } + + detail.push_str(segment); + } + + detail +} + fn params_display(db: &dyn HirDatabase, func: hir::Function) -> String { if let Some(self_param) = func.self_param(db) { let assoc_fn_params = func.assoc_fn_params(db);