2019-10-27 08:56:53 -05:00
|
|
|
use ra_syntax::{
|
|
|
|
algo::non_trivia_sibling,
|
|
|
|
ast::{self, AstNode},
|
|
|
|
Direction, T,
|
|
|
|
};
|
2019-10-26 15:24:48 -05:00
|
|
|
|
2020-06-28 17:36:05 -05:00
|
|
|
use crate::{AssistContext, AssistId, AssistKind, Assists};
|
2019-10-26 15:24:48 -05:00
|
|
|
|
2019-10-27 08:56:53 -05:00
|
|
|
// Assist: flip_trait_bound
|
|
|
|
//
|
|
|
|
// Flips two trait bounds.
|
|
|
|
//
|
|
|
|
// ```
|
|
|
|
// fn foo<T: Clone +<|> Copy>() { }
|
|
|
|
// ```
|
|
|
|
// ->
|
|
|
|
// ```
|
|
|
|
// fn foo<T: Copy + Clone>() { }
|
|
|
|
// ```
|
2020-05-06 11:45:35 -05:00
|
|
|
pub(crate) fn flip_trait_bound(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
|
2019-10-26 15:24:48 -05:00
|
|
|
// We want to replicate the behavior of `flip_binexpr` by only suggesting
|
|
|
|
// the assist when the cursor is on a `+`
|
2019-10-27 08:56:53 -05:00
|
|
|
let plus = ctx.find_token_at_offset(T![+])?;
|
|
|
|
|
|
|
|
// Make sure we're in a `TypeBoundList`
|
|
|
|
if ast::TypeBoundList::cast(plus.parent()).is_none() {
|
|
|
|
return None;
|
|
|
|
}
|
2019-10-26 15:24:48 -05:00
|
|
|
|
|
|
|
let (before, after) = (
|
|
|
|
non_trivia_sibling(plus.clone().into(), Direction::Prev)?,
|
|
|
|
non_trivia_sibling(plus.clone().into(), Direction::Next)?,
|
|
|
|
);
|
|
|
|
|
2020-05-06 05:51:28 -05:00
|
|
|
let target = plus.text_range();
|
2020-06-28 17:36:05 -05:00
|
|
|
acc.add(
|
|
|
|
AssistId("flip_trait_bound"),
|
|
|
|
AssistKind::RefactorRewrite,
|
|
|
|
"Flip trait bounds",
|
|
|
|
target,
|
|
|
|
|edit| {
|
|
|
|
edit.replace(before.text_range(), after.to_string());
|
|
|
|
edit.replace(after.text_range(), before.to_string());
|
|
|
|
},
|
|
|
|
)
|
2019-10-26 15:24:48 -05:00
|
|
|
}
|
2019-10-26 15:27:50 -05:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
2020-05-06 03:16:55 -05:00
|
|
|
use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
|
2019-10-26 15:27:50 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn flip_trait_bound_assist_available() {
|
|
|
|
check_assist_target(flip_trait_bound, "struct S<T> where T: A <|>+ B + C { }", "+")
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn flip_trait_bound_not_applicable_for_single_trait_bound() {
|
|
|
|
check_assist_not_applicable(flip_trait_bound, "struct S<T> where T: <|>A { }")
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn flip_trait_bound_works_for_struct() {
|
|
|
|
check_assist(
|
|
|
|
flip_trait_bound,
|
|
|
|
"struct S<T> where T: A <|>+ B { }",
|
2020-05-20 15:55:37 -05:00
|
|
|
"struct S<T> where T: B + A { }",
|
2019-10-26 15:27:50 -05:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn flip_trait_bound_works_for_trait_impl() {
|
|
|
|
check_assist(
|
|
|
|
flip_trait_bound,
|
|
|
|
"impl X for S<T> where T: A +<|> B { }",
|
2020-05-20 15:55:37 -05:00
|
|
|
"impl X for S<T> where T: B + A { }",
|
2019-10-26 15:27:50 -05:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn flip_trait_bound_works_for_fn() {
|
2020-05-20 15:55:37 -05:00
|
|
|
check_assist(flip_trait_bound, "fn f<T: A <|>+ B>(t: T) { }", "fn f<T: B + A>(t: T) { }")
|
2019-10-26 15:27:50 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn flip_trait_bound_works_for_fn_where_clause() {
|
|
|
|
check_assist(
|
|
|
|
flip_trait_bound,
|
|
|
|
"fn f<T>(t: T) where T: A +<|> B { }",
|
2020-05-20 15:55:37 -05:00
|
|
|
"fn f<T>(t: T) where T: B + A { }",
|
2019-10-26 15:27:50 -05:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn flip_trait_bound_works_for_lifetime() {
|
|
|
|
check_assist(
|
|
|
|
flip_trait_bound,
|
|
|
|
"fn f<T>(t: T) where T: A <|>+ 'static { }",
|
2020-05-20 15:55:37 -05:00
|
|
|
"fn f<T>(t: T) where T: 'static + A { }",
|
2019-10-26 15:27:50 -05:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn flip_trait_bound_works_for_complex_bounds() {
|
|
|
|
check_assist(
|
|
|
|
flip_trait_bound,
|
|
|
|
"struct S<T> where T: A<T> <|>+ b_mod::B<T> + C<T> { }",
|
2020-05-20 15:55:37 -05:00
|
|
|
"struct S<T> where T: b_mod::B<T> + A<T> + C<T> { }",
|
2019-10-26 15:27:50 -05:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn flip_trait_bound_works_for_long_bounds() {
|
|
|
|
check_assist(
|
|
|
|
flip_trait_bound,
|
|
|
|
"struct S<T> where T: A + B + C + D + E + F +<|> G + H + I + J { }",
|
2020-05-20 15:55:37 -05:00
|
|
|
"struct S<T> where T: A + B + C + D + E + G + F + H + I + J { }",
|
2019-10-26 15:27:50 -05:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|