Auto merge of #15582 - vxpm:master, r=HKalbasi

add option to show full function signatures in completion docs

implements #15538

with `"rust-analyzer.completion.fullFunctionSignatures.enable": false`:
![image](https://github.com/rust-lang/rust-analyzer/assets/59714841/ff739ad1-9975-461f-a62d-22c7823e7b71)

with `"rust-analyzer.completion.fullFunctionSignatures.enable": true`:
![image](https://github.com/rust-lang/rust-analyzer/assets/59714841/9bc98300-cef6-44ef-a353-dcf35cd36fce)
This commit is contained in:
bors 2023-09-24 07:38:38 +00:00
commit e5e937ae5e
8 changed files with 109 additions and 3 deletions

View File

@ -14,6 +14,7 @@ pub struct CompletionConfig {
pub enable_imports_on_the_fly: bool, pub enable_imports_on_the_fly: bool,
pub enable_self_on_the_fly: bool, pub enable_self_on_the_fly: bool,
pub enable_private_editable: bool, pub enable_private_editable: bool,
pub full_function_signatures: bool,
pub callable: Option<CallableSnippets>, pub callable: Option<CallableSnippets>,
pub snippet_cap: Option<SnippetCap>, pub snippet_cap: Option<SnippetCap>,
pub insert_use: InsertUseConfig, pub insert_use: InsertUseConfig,

View File

@ -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)) item.set_documentation(ctx.docs(func))
.set_deprecated(ctx.is_deprecated(func) || ctx.is_deprecated_assoc_item(func)) .set_deprecated(ctx.is_deprecated(func) || ctx.is_deprecated_assoc_item(func))
.detail(detail(db, func)) .detail(detail)
.lookup_by(name.unescaped().to_smol_str()); .lookup_by(name.unescaped().to_smol_str());
match ctx.completion.config.snippet_cap { match ctx.completion.config.snippet_cap {
@ -263,6 +268,21 @@ fn detail(db: &dyn HirDatabase, func: hir::Function) -> String {
detail 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 { fn params_display(db: &dyn HirDatabase, func: hir::Function) -> String {
if let Some(self_param) = func.self_param(db) { if let Some(self_param) = func.self_param(db) {
let assoc_fn_params = func.assoc_fn_params(db); let assoc_fn_params = func.assoc_fn_params(db);

View File

@ -64,6 +64,7 @@ union Union { field: i32 }
enable_imports_on_the_fly: true, enable_imports_on_the_fly: true,
enable_self_on_the_fly: true, enable_self_on_the_fly: true,
enable_private_editable: false, enable_private_editable: false,
full_function_signatures: false,
callable: Some(CallableSnippets::FillArguments), callable: Some(CallableSnippets::FillArguments),
snippet_cap: SnippetCap::new(true), snippet_cap: SnippetCap::new(true),
prefer_no_std: false, prefer_no_std: false,

View File

@ -2,10 +2,15 @@
use expect_test::{expect, Expect}; use expect_test::{expect, Expect};
use crate::tests::{ use crate::{
check_edit, completion_list, completion_list_no_kw, completion_list_with_trigger_character, 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) { fn check_no_kw(ra_fixture: &str, expect: Expect) {
let actual = completion_list_no_kw(ra_fixture); let actual = completion_list_no_kw(ra_fixture);
expect.assert_eq(&actual) expect.assert_eq(&actual)
@ -1303,3 +1308,67 @@ struct Foo<T: PartialOrd
"#, "#,
); );
} }
fn check_signatures(src: &str, kind: CompletionItemKind, reduced: Expect, full: Expect) {
const FULL_SIGNATURES_CONFIG: crate::CompletionConfig = {
let mut x = TEST_CONFIG;
x.full_function_signatures = true;
x
};
// reduced signature
let completion = do_completion_with_config(TEST_CONFIG, src, kind);
assert!(completion[0].detail.is_some());
reduced.assert_eq(completion[0].detail.as_ref().unwrap());
// full signature
let completion = do_completion_with_config(FULL_SIGNATURES_CONFIG, src, kind);
assert!(completion[0].detail.is_some());
full.assert_eq(completion[0].detail.as_ref().unwrap());
}
#[test]
fn respects_full_function_signatures() {
check_signatures(
r#"
pub fn foo<'x, T>(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) -> !"),
);
}

View File

@ -217,6 +217,8 @@ struct ConfigData {
completion_autoself_enable: bool = "true", completion_autoself_enable: bool = "true",
/// Whether to add parenthesis and argument snippets when completing function. /// Whether to add parenthesis and argument snippets when completing function.
completion_callable_snippets: CallableCompletionDef = "\"fill_arguments\"", 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. /// Maximum number of completions to return. If `None`, the limit is infinite.
completion_limit: Option<usize> = "null", completion_limit: Option<usize> = "null",
/// Whether to show postfix snippets like `dbg`, `if`, `not`, etc. /// Whether to show postfix snippets like `dbg`, `if`, `not`, etc.
@ -1455,6 +1457,7 @@ pub fn completion(&self) -> CompletionConfig {
&& completion_item_edit_resolve(&self.caps), && completion_item_edit_resolve(&self.caps),
enable_self_on_the_fly: self.data.completion_autoself_enable, enable_self_on_the_fly: self.data.completion_autoself_enable,
enable_private_editable: self.data.completion_privateEditable_enable, enable_private_editable: self.data.completion_privateEditable_enable,
full_function_signatures: self.data.completion_fullFunctionSignatures_enable,
callable: match self.data.completion_callable_snippets { callable: match self.data.completion_callable_snippets {
CallableCompletionDef::FillArguments => Some(CallableSnippets::FillArguments), CallableCompletionDef::FillArguments => Some(CallableSnippets::FillArguments),
CallableCompletionDef::AddParentheses => Some(CallableSnippets::AddParentheses), CallableCompletionDef::AddParentheses => Some(CallableSnippets::AddParentheses),

View File

@ -134,6 +134,7 @@ fn integrated_completion_benchmark() {
enable_imports_on_the_fly: true, enable_imports_on_the_fly: true,
enable_self_on_the_fly: true, enable_self_on_the_fly: true,
enable_private_editable: true, enable_private_editable: true,
full_function_signatures: false,
callable: Some(CallableSnippets::FillArguments), callable: Some(CallableSnippets::FillArguments),
snippet_cap: SnippetCap::new(true), snippet_cap: SnippetCap::new(true),
insert_use: InsertUseConfig { insert_use: InsertUseConfig {
@ -173,6 +174,7 @@ fn integrated_completion_benchmark() {
enable_imports_on_the_fly: true, enable_imports_on_the_fly: true,
enable_self_on_the_fly: true, enable_self_on_the_fly: true,
enable_private_editable: true, enable_private_editable: true,
full_function_signatures: false,
callable: Some(CallableSnippets::FillArguments), callable: Some(CallableSnippets::FillArguments),
snippet_cap: SnippetCap::new(true), snippet_cap: SnippetCap::new(true),
insert_use: InsertUseConfig { insert_use: InsertUseConfig {

View File

@ -252,6 +252,11 @@ with `self` prefixed to them when inside a method.
-- --
Whether to add parenthesis and argument snippets when completing function. 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`):: [[rust-analyzer.completion.limit]]rust-analyzer.completion.limit (default: `null`)::
+ +
-- --

View File

@ -799,6 +799,11 @@
"Do no snippet completions for callables." "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": { "rust-analyzer.completion.limit": {
"markdownDescription": "Maximum number of completions to return. If `None`, the limit is infinite.", "markdownDescription": "Maximum number of completions to return. If `None`, the limit is infinite.",
"default": null, "default": null,