11220: Turbo fish assist: don't include lifetime parameters r=Veykril a=Vannevelj

Fixes #11219

The issue talks about three different types of params: type, const & lifetime. I wasn't entirely sure which ones are intended to be included here so I've gone for the type & const params (i.e. exclude lifetime).

I've added a test case for both a lifetime param and a const param. I'm still making my way through the rust book (chapter 7, yay) so I'm not too sure yet what these are but my testing shows that this approach generates code that compiles.

Co-authored-by: Jeroen Vannevel <jer_vannevel@outlook.com>
This commit is contained in:
bors[bot] 2022-01-07 14:02:01 +00:00 committed by GitHub
commit efb9b89163
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,4 +1,5 @@
use ide_db::defs::{Definition, NameRefClass};
use itertools::Itertools;
use syntax::{ast, AstNode, SyntaxKind, T};
use crate::{
@ -77,8 +78,12 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<(
}
}
let number_of_arguments = generics.len();
let fish_head = std::iter::repeat("_").take(number_of_arguments).collect::<Vec<_>>().join(",");
let number_of_arguments = generics
.iter()
.filter(|param| {
matches!(param, hir::GenericParam::TypeParam(_) | hir::GenericParam::ConstParam(_))
})
.count();
acc.add(
AssistId("add_turbo_fish", AssistKind::RefactorRewrite),
@ -86,10 +91,11 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<(
ident.text_range(),
|builder| match ctx.config.snippet_cap {
Some(cap) => {
let snip = format!("::<${{0:{}}}>", fish_head);
let snip = format!("::<{}>", get_snippet_fish_head(number_of_arguments));
builder.insert_snippet(cap, ident.text_range().end(), snip)
}
None => {
let fish_head = std::iter::repeat("_").take(number_of_arguments).format(", ");
let snip = format!("::<{}>", fish_head);
builder.insert(ident.text_range().end(), snip);
}
@ -97,6 +103,17 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext) -> Option<(
)
}
/// This will create a snippet string with tabstops marked
fn get_snippet_fish_head(number_of_arguments: usize) -> String {
let mut fish_head = (1..number_of_arguments)
.format_with("", |i, f| f(&format_args!("${{{}:_}}, ", i)))
.to_string();
// tabstop 0 is a special case and always the last one
fish_head.push_str("${0:_}");
fish_head
}
#[cfg(test)]
mod tests {
use crate::tests::{check_assist, check_assist_by_label, check_assist_not_applicable};
@ -135,7 +152,7 @@ fn main() {
r#"
fn make<T, A>() -> T {}
fn main() {
make::<${0:_,_}>();
make::<${1:_}, ${0:_}>();
}
"#,
);
@ -154,7 +171,7 @@ fn main() {
r#"
fn make<T, A, B, C, D, E, F>() -> T {}
fn main() {
make::<${0:_,_,_,_,_,_,_}>();
make::<${1:_}, ${2:_}, ${3:_}, ${4:_}, ${5:_}, ${6:_}, ${0:_}>();
}
"#,
);
@ -339,4 +356,42 @@ fn main() {
"Add `: _` before assignment operator",
);
}
#[test]
fn add_turbo_fish_function_lifetime_parameter() {
check_assist(
add_turbo_fish,
r#"
fn make<'a, T, A>(t: T, a: A) {}
fn main() {
make$0(5, 2);
}
"#,
r#"
fn make<'a, T, A>(t: T, a: A) {}
fn main() {
make::<${1:_}, ${0:_}>(5, 2);
}
"#,
);
}
#[test]
fn add_turbo_fish_function_const_parameter() {
check_assist(
add_turbo_fish,
r#"
fn make<T, const N: usize>(t: T) {}
fn main() {
make$0(3);
}
"#,
r#"
fn make<T, const N: usize>(t: T) {}
fn main() {
make::<${1:_}, ${0:_}>(3);
}
"#,
);
}
}