ra_ap_ide_assists/handlers/
flip_trait_bound.rs1use syntax::{
2 Direction, T,
3 algo::non_trivia_sibling,
4 ast::{self, AstNode},
5};
6
7use crate::{AssistContext, AssistId, Assists};
8
9pub(crate) fn flip_trait_bound(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
21 let plus = ctx.find_token_syntax_at_offset(T![+])?;
23
24 let parent = ast::TypeBoundList::cast(plus.parent()?)?;
26
27 let before = non_trivia_sibling(plus.clone().into(), Direction::Prev)?.into_node()?;
28 let after = non_trivia_sibling(plus.clone().into(), Direction::Next)?.into_node()?;
29
30 let target = plus.text_range();
31 acc.add(
32 AssistId::refactor_rewrite("flip_trait_bound"),
33 "Flip trait bounds",
34 target,
35 |builder| {
36 let mut editor = builder.make_editor(parent.syntax());
37 editor.replace(before.clone(), after.clone());
38 editor.replace(after, before);
39 builder.add_file_edits(ctx.vfs_file_id(), editor);
40 },
41 )
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47
48 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
49
50 #[test]
51 fn flip_trait_bound_assist_available() {
52 check_assist_target(flip_trait_bound, "struct S<T> where T: A $0+ B + C { }", "+")
53 }
54
55 #[test]
56 fn flip_trait_bound_not_applicable_for_single_trait_bound() {
57 check_assist_not_applicable(flip_trait_bound, "struct S<T> where T: $0A { }")
58 }
59
60 #[test]
61 fn flip_trait_bound_works_for_dyn() {
62 check_assist(flip_trait_bound, "fn f<'a>(x: dyn Copy $0+ 'a)", "fn f<'a>(x: dyn 'a + Copy)")
63 }
64
65 #[test]
66 fn flip_trait_bound_works_for_struct() {
67 check_assist(
68 flip_trait_bound,
69 "struct S<T> where T: A $0+ B { }",
70 "struct S<T> where T: B + A { }",
71 )
72 }
73
74 #[test]
75 fn flip_trait_bound_works_for_trait_impl() {
76 check_assist(
77 flip_trait_bound,
78 "impl X for S<T> where T: A +$0 B { }",
79 "impl X for S<T> where T: B + A { }",
80 )
81 }
82
83 #[test]
84 fn flip_trait_bound_works_for_fn() {
85 check_assist(flip_trait_bound, "fn f<T: A $0+ B>(t: T) { }", "fn f<T: B + A>(t: T) { }")
86 }
87
88 #[test]
89 fn flip_trait_bound_works_for_fn_where_clause() {
90 check_assist(
91 flip_trait_bound,
92 "fn f<T>(t: T) where T: A +$0 B { }",
93 "fn f<T>(t: T) where T: B + A { }",
94 )
95 }
96
97 #[test]
98 fn flip_trait_bound_works_for_lifetime() {
99 check_assist(
100 flip_trait_bound,
101 "fn f<T>(t: T) where T: A $0+ 'static { }",
102 "fn f<T>(t: T) where T: 'static + A { }",
103 )
104 }
105
106 #[test]
107 fn flip_trait_bound_works_for_complex_bounds() {
108 check_assist(
109 flip_trait_bound,
110 "struct S<T> where T: A<T> $0+ b_mod::B<T> + C<T> { }",
111 "struct S<T> where T: b_mod::B<T> + A<T> + C<T> { }",
112 )
113 }
114
115 #[test]
116 fn flip_trait_bound_works_for_long_bounds() {
117 check_assist(
118 flip_trait_bound,
119 "struct S<T> where T: A + B + C + D + E + F +$0 G + H + I + J { }",
120 "struct S<T> where T: A + B + C + D + E + G + F + H + I + J { }",
121 )
122 }
123}