From 561b4b11ff1d87ea1ff2477dcba6ae1f396573a3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 7 Feb 2020 15:53:31 +0100 Subject: Name assist handlers --- crates/ra_assists/src/handlers/flip_trait_bound.rs | 116 +++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 crates/ra_assists/src/handlers/flip_trait_bound.rs (limited to 'crates/ra_assists/src/handlers/flip_trait_bound.rs') diff --git a/crates/ra_assists/src/handlers/flip_trait_bound.rs b/crates/ra_assists/src/handlers/flip_trait_bound.rs new file mode 100644 index 000000000..f56769624 --- /dev/null +++ b/crates/ra_assists/src/handlers/flip_trait_bound.rs @@ -0,0 +1,116 @@ +use ra_syntax::{ + algo::non_trivia_sibling, + ast::{self, AstNode}, + Direction, T, +}; + +use crate::{Assist, AssistCtx, AssistId}; + +// Assist: flip_trait_bound +// +// Flips two trait bounds. +// +// ``` +// fn foo Copy>() { } +// ``` +// -> +// ``` +// fn foo() { } +// ``` +pub(crate) fn flip_trait_bound(ctx: AssistCtx) -> Option { + // We want to replicate the behavior of `flip_binexpr` by only suggesting + // the assist when the cursor is on a `+` + 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; + } + + let (before, after) = ( + non_trivia_sibling(plus.clone().into(), Direction::Prev)?, + non_trivia_sibling(plus.clone().into(), Direction::Next)?, + ); + + ctx.add_assist(AssistId("flip_trait_bound"), "Flip trait bounds", |edit| { + edit.target(plus.text_range()); + edit.replace(before.text_range(), after.to_string()); + edit.replace(after.text_range(), before.to_string()); + }) +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; + + #[test] + fn flip_trait_bound_assist_available() { + check_assist_target(flip_trait_bound, "struct S 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 where T: <|>A { }") + } + + #[test] + fn flip_trait_bound_works_for_struct() { + check_assist( + flip_trait_bound, + "struct S where T: A <|>+ B { }", + "struct S where T: B <|>+ A { }", + ) + } + + #[test] + fn flip_trait_bound_works_for_trait_impl() { + check_assist( + flip_trait_bound, + "impl X for S where T: A +<|> B { }", + "impl X for S where T: B +<|> A { }", + ) + } + + #[test] + fn flip_trait_bound_works_for_fn() { + check_assist(flip_trait_bound, "fn f+ B>(t: T) { }", "fn f+ A>(t: T) { }") + } + + #[test] + fn flip_trait_bound_works_for_fn_where_clause() { + check_assist( + flip_trait_bound, + "fn f(t: T) where T: A +<|> B { }", + "fn f(t: T) where T: B +<|> A { }", + ) + } + + #[test] + fn flip_trait_bound_works_for_lifetime() { + check_assist( + flip_trait_bound, + "fn f(t: T) where T: A <|>+ 'static { }", + "fn f(t: T) where T: 'static <|>+ A { }", + ) + } + + #[test] + fn flip_trait_bound_works_for_complex_bounds() { + check_assist( + flip_trait_bound, + "struct S where T: A <|>+ b_mod::B + C { }", + "struct S where T: b_mod::B <|>+ A + C { }", + ) + } + + #[test] + fn flip_trait_bound_works_for_long_bounds() { + check_assist( + flip_trait_bound, + "struct S where T: A + B + C + D + E + F +<|> G + H + I + J { }", + "struct S where T: A + B + C + D + E + G +<|> F + H + I + J { }", + ) + } +} -- cgit v1.2.3