From a58f7acc97198af1e2d511a90609be9a8b67882b Mon Sep 17 00:00:00 2001 From: rainy-me Date: Wed, 20 Apr 2022 17:56:20 +0900 Subject: [PATCH 1/2] fix: improve parameter completion --- .../src/completions/fn_param.rs | 20 +++--- crates/ide_completion/src/render/function.rs | 72 +++++++++++++++++++ crates/ide_completion/src/tests/fn_param.rs | 13 ++++ 3 files changed, 96 insertions(+), 9 deletions(-) diff --git a/crates/ide_completion/src/completions/fn_param.rs b/crates/ide_completion/src/completions/fn_param.rs index 7e9c1f49de..5bfd2bc1df 100644 --- a/crates/ide_completion/src/completions/fn_param.rs +++ b/crates/ide_completion/src/completions/fn_param.rs @@ -5,7 +5,7 @@ use rustc_hash::FxHashMap; use syntax::{ algo, ast::{self, HasModuleItem}, - match_ast, AstNode, Direction, SyntaxKind, + match_ast, AstNode, Direction, SyntaxKind, TextRange, }; use crate::{ @@ -27,12 +27,12 @@ pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) let comma_wrapper = comma_wrapper(ctx); let mut add_new_item_to_acc = |label: &str, lookup: String| { - let mk_item = |label: &str| { - CompletionItem::new(CompletionItemKind::Binding, ctx.source_range(), label) + let mk_item = |label: &str, range: TextRange| { + CompletionItem::new(CompletionItemKind::Binding, range, label) }; let mut item = match &comma_wrapper { - Some(fmt) => mk_item(&fmt(label)), - None => mk_item(label), + Some((fmt, range)) => mk_item(&fmt(label), *range), + None => mk_item(label, ctx.source_range()), }; item.lookup_by(lookup); item.add_to(acc) @@ -162,14 +162,16 @@ fn should_add_self_completions(ctx: &CompletionContext, param_list: &ast::ParamL inside_impl && no_params } -fn comma_wrapper(ctx: &CompletionContext) -> Option String> { +fn comma_wrapper(ctx: &CompletionContext) -> Option<(impl Fn(&str) -> String, TextRange)> { + let param = ctx.token.ancestors().find(|node| node.kind() == SyntaxKind::PARAM)?; + let next_token_kind = { - let t = ctx.token.next_token()?; + let t = param.last_token()?.next_token()?; let t = algo::skip_whitespace_token(t, Direction::Next)?; t.kind() }; let prev_token_kind = { - let t = ctx.previous_token.clone()?; + let t = param.first_token()?.prev_token()?; let t = algo::skip_whitespace_token(t, Direction::Prev)?; t.kind() }; @@ -182,5 +184,5 @@ fn comma_wrapper(ctx: &CompletionContext) -> Option String> { matches!(prev_token_kind, SyntaxKind::COMMA | SyntaxKind::L_PAREN | SyntaxKind::PIPE); let leading = if has_leading_comma { "" } else { ", " }; - Some(move |param: &_| format!("{}{}{}", leading, param, trailing)) + Some((move |label: &_| (format!("{}{}{}", leading, label, trailing)), param.text_range())) } diff --git a/crates/ide_completion/src/render/function.rs b/crates/ide_completion/src/render/function.rs index 9e5f91db39..2ae300ab65 100644 --- a/crates/ide_completion/src/render/function.rs +++ b/crates/ide_completion/src/render/function.rs @@ -562,6 +562,78 @@ fn qux(Foo { bar }: Foo) { fn main() { qux(${1:foo})$0 } +"#, + ); + } + + #[test] + fn complete_fn_param() { + // has mut kw + check_edit( + "mut bar", + r#" +fn f(foo: (), mut bar: u32) {} +fn g(foo: (), mut ba$0) +"#, + r#" +fn f(foo: (), mut bar: u32) {} +fn g(foo: (), mut bar: u32) +"#, + ); + + // has type param + check_edit( + "mut bar", + r#" +fn g(foo: (), mut ba$0: u32) +fn f(foo: (), mut bar: u32) {} +"#, + r#" +fn g(foo: (), mut bar: u32) +fn f(foo: (), mut bar: u32) {} +"#, + ); + } + + #[test] + fn complete_fn_mut_param_add_comma() { + // add leading and trailing comma + check_edit( + "mut bar", + r#" +fn f(foo: (), mut bar: u32) {} +fn g(foo: ()mut ba$0 baz: ()) +"#, + r#" +fn f(foo: (), mut bar: u32) {} +fn g(foo: (), mut bar: u32, baz: ()) +"#, + ); + } + + #[test] + fn complete_fn_mut_param_has_attribute() { + check_edit( + "mut bar", + r#" +fn f(foo: (), #[baz = "qux"] mut bar: u32) {} +fn g(foo: (), mut ba$0) +"#, + r#" +fn f(foo: (), #[baz = "qux"] mut bar: u32) {} +fn g(foo: (), #[baz = "qux"] mut bar: u32) +"#, + ); + + check_edit( + "mut bar", + r#" +fn f(foo: (), #[baz = "qux"] mut bar: u32) {} +fn g(foo: (), #[baz = "qux"] mut ba$0) +"#, + r#" +fn f(foo: (), #[baz = "qux"] mut bar: u32) {} +fn g(foo: (), #[baz = "qux"] mut bar: u32) "#, ); } diff --git a/crates/ide_completion/src/tests/fn_param.rs b/crates/ide_completion/src/tests/fn_param.rs index 779ec0c3a7..678c99aa7a 100644 --- a/crates/ide_completion/src/tests/fn_param.rs +++ b/crates/ide_completion/src/tests/fn_param.rs @@ -232,3 +232,16 @@ fn bar(bar$0) {} "#]], ) } + +#[test] +fn completes_for_params_with_attributes() { + check( + r#" +fn f(foo: (), #[baz = "qux"] mut bar: u32) {} +fn g(foo: (), #[baz = "qux"] mut ba$0) +"#, + expect![[r##" + bn #[baz = "qux"] mut bar: u32 + "##]], + ) +} From 8f8f20fda5936faff04f9c5c3c8880bd4572900f Mon Sep 17 00:00:00 2001 From: rainy-me Date: Fri, 22 Apr 2022 00:07:42 +0900 Subject: [PATCH 2/2] fix: lookup --- .../src/completions/fn_param.rs | 15 ++++++++----- crates/ide_completion/src/render/function.rs | 22 ++++++++++++++----- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/crates/ide_completion/src/completions/fn_param.rs b/crates/ide_completion/src/completions/fn_param.rs index 5bfd2bc1df..ae09339e95 100644 --- a/crates/ide_completion/src/completions/fn_param.rs +++ b/crates/ide_completion/src/completions/fn_param.rs @@ -30,11 +30,10 @@ pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext) let mk_item = |label: &str, range: TextRange| { CompletionItem::new(CompletionItemKind::Binding, range, label) }; - let mut item = match &comma_wrapper { - Some((fmt, range)) => mk_item(&fmt(label), *range), - None => mk_item(label, ctx.source_range()), + let item = match &comma_wrapper { + Some((fmt, range, lookup)) => mk_item(&fmt(label), *range).lookup_by(lookup).to_owned(), + None => mk_item(label, ctx.source_range()).lookup_by(lookup).to_owned(), }; - item.lookup_by(lookup); item.add_to(acc) }; @@ -162,7 +161,7 @@ fn should_add_self_completions(ctx: &CompletionContext, param_list: &ast::ParamL inside_impl && no_params } -fn comma_wrapper(ctx: &CompletionContext) -> Option<(impl Fn(&str) -> String, TextRange)> { +fn comma_wrapper(ctx: &CompletionContext) -> Option<(impl Fn(&str) -> String, TextRange, String)> { let param = ctx.token.ancestors().find(|node| node.kind() == SyntaxKind::PARAM)?; let next_token_kind = { @@ -184,5 +183,9 @@ fn comma_wrapper(ctx: &CompletionContext) -> Option<(impl Fn(&str) -> String, Te matches!(prev_token_kind, SyntaxKind::COMMA | SyntaxKind::L_PAREN | SyntaxKind::PIPE); let leading = if has_leading_comma { "" } else { ", " }; - Some((move |label: &_| (format!("{}{}{}", leading, label, trailing)), param.text_range())) + Some(( + move |label: &_| (format!("{}{}{}", leading, label, trailing)), + param.text_range(), + format!("{}{}", leading, param.text()), + )) } diff --git a/crates/ide_completion/src/render/function.rs b/crates/ide_completion/src/render/function.rs index 2ae300ab65..bd6833567c 100644 --- a/crates/ide_completion/src/render/function.rs +++ b/crates/ide_completion/src/render/function.rs @@ -570,7 +570,7 @@ fn main() { fn complete_fn_param() { // has mut kw check_edit( - "mut bar", + "mut ba", r#" fn f(foo: (), mut bar: u32) {} fn g(foo: (), mut ba$0) @@ -583,7 +583,7 @@ fn g(foo: (), mut bar: u32) // has type param check_edit( - "mut bar", + "mut ba: u32", r#" fn g(foo: (), mut ba$0: u32) fn f(foo: (), mut bar: u32) {} @@ -599,7 +599,7 @@ fn f(foo: (), mut bar: u32) {} fn complete_fn_mut_param_add_comma() { // add leading and trailing comma check_edit( - "mut bar", + ", mut ba", r#" fn f(foo: (), mut bar: u32) {} fn g(foo: ()mut ba$0 baz: ()) @@ -614,7 +614,7 @@ fn g(foo: (), mut bar: u32, baz: ()) #[test] fn complete_fn_mut_param_has_attribute() { check_edit( - "mut bar", + "mut ba", r#" fn f(foo: (), #[baz = "qux"] mut bar: u32) {} fn g(foo: (), mut ba$0) @@ -626,7 +626,7 @@ fn g(foo: (), #[baz = "qux"] mut bar: u32) ); check_edit( - "mut bar", + r#"#[baz = "qux"] mut ba"#, r#" fn f(foo: (), #[baz = "qux"] mut bar: u32) {} fn g(foo: (), #[baz = "qux"] mut ba$0) @@ -634,6 +634,18 @@ fn g(foo: (), #[baz = "qux"] mut ba$0) r#" fn f(foo: (), #[baz = "qux"] mut bar: u32) {} fn g(foo: (), #[baz = "qux"] mut bar: u32) +"#, + ); + + check_edit( + r#", #[baz = "qux"] mut ba"#, + r#" +fn f(foo: (), #[baz = "qux"] mut bar: u32) {} +fn g(foo: ()#[baz = "qux"] mut ba$0) +"#, + r#" +fn f(foo: (), #[baz = "qux"] mut bar: u32) {} +fn g(foo: (), #[baz = "qux"] mut bar: u32) "#, ); }