diff options
author | Kevin DeLorey <[email protected]> | 2020-02-09 16:25:47 +0000 |
---|---|---|
committer | Kevin DeLorey <[email protected]> | 2020-02-09 16:37:43 +0000 |
commit | a957c473fdb79880c39b73dc9e0c923093cf16ac (patch) | |
tree | f998b548f530ce604651e0e6af314ed2ec74b3b5 /crates/ra_assists/src/handlers/flip_trait_bound.rs | |
parent | 22caf982b99c54058e2e9200aeea0e61cada284a (diff) | |
parent | 1b9b13b4b4a75b5531c3f046ce6bf72d681f2732 (diff) |
Merge branch 'master' into kdelorey/complete-trait-impl
Diffstat (limited to 'crates/ra_assists/src/handlers/flip_trait_bound.rs')
-rw-r--r-- | crates/ra_assists/src/handlers/flip_trait_bound.rs | 116 |
1 files changed, 116 insertions, 0 deletions
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 @@ | |||
1 | use ra_syntax::{ | ||
2 | algo::non_trivia_sibling, | ||
3 | ast::{self, AstNode}, | ||
4 | Direction, T, | ||
5 | }; | ||
6 | |||
7 | use crate::{Assist, AssistCtx, AssistId}; | ||
8 | |||
9 | // Assist: flip_trait_bound | ||
10 | // | ||
11 | // Flips two trait bounds. | ||
12 | // | ||
13 | // ``` | ||
14 | // fn foo<T: Clone +<|> Copy>() { } | ||
15 | // ``` | ||
16 | // -> | ||
17 | // ``` | ||
18 | // fn foo<T: Copy + Clone>() { } | ||
19 | // ``` | ||
20 | pub(crate) fn flip_trait_bound(ctx: AssistCtx) -> Option<Assist> { | ||
21 | // We want to replicate the behavior of `flip_binexpr` by only suggesting | ||
22 | // the assist when the cursor is on a `+` | ||
23 | let plus = ctx.find_token_at_offset(T![+])?; | ||
24 | |||
25 | // Make sure we're in a `TypeBoundList` | ||
26 | if ast::TypeBoundList::cast(plus.parent()).is_none() { | ||
27 | return None; | ||
28 | } | ||
29 | |||
30 | let (before, after) = ( | ||
31 | non_trivia_sibling(plus.clone().into(), Direction::Prev)?, | ||
32 | non_trivia_sibling(plus.clone().into(), Direction::Next)?, | ||
33 | ); | ||
34 | |||
35 | ctx.add_assist(AssistId("flip_trait_bound"), "Flip trait bounds", |edit| { | ||
36 | edit.target(plus.text_range()); | ||
37 | edit.replace(before.text_range(), after.to_string()); | ||
38 | edit.replace(after.text_range(), before.to_string()); | ||
39 | }) | ||
40 | } | ||
41 | |||
42 | #[cfg(test)] | ||
43 | mod tests { | ||
44 | use super::*; | ||
45 | |||
46 | use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; | ||
47 | |||
48 | #[test] | ||
49 | fn flip_trait_bound_assist_available() { | ||
50 | check_assist_target(flip_trait_bound, "struct S<T> where T: A <|>+ B + C { }", "+") | ||
51 | } | ||
52 | |||
53 | #[test] | ||
54 | fn flip_trait_bound_not_applicable_for_single_trait_bound() { | ||
55 | check_assist_not_applicable(flip_trait_bound, "struct S<T> where T: <|>A { }") | ||
56 | } | ||
57 | |||
58 | #[test] | ||
59 | fn flip_trait_bound_works_for_struct() { | ||
60 | check_assist( | ||
61 | flip_trait_bound, | ||
62 | "struct S<T> where T: A <|>+ B { }", | ||
63 | "struct S<T> where T: B <|>+ A { }", | ||
64 | ) | ||
65 | } | ||
66 | |||
67 | #[test] | ||
68 | fn flip_trait_bound_works_for_trait_impl() { | ||
69 | check_assist( | ||
70 | flip_trait_bound, | ||
71 | "impl X for S<T> where T: A +<|> B { }", | ||
72 | "impl X for S<T> where T: B +<|> A { }", | ||
73 | ) | ||
74 | } | ||
75 | |||
76 | #[test] | ||
77 | fn flip_trait_bound_works_for_fn() { | ||
78 | check_assist(flip_trait_bound, "fn f<T: A <|>+ B>(t: T) { }", "fn f<T: B <|>+ A>(t: T) { }") | ||
79 | } | ||
80 | |||
81 | #[test] | ||
82 | fn flip_trait_bound_works_for_fn_where_clause() { | ||
83 | check_assist( | ||
84 | flip_trait_bound, | ||
85 | "fn f<T>(t: T) where T: A +<|> B { }", | ||
86 | "fn f<T>(t: T) where T: B +<|> A { }", | ||
87 | ) | ||
88 | } | ||
89 | |||
90 | #[test] | ||
91 | fn flip_trait_bound_works_for_lifetime() { | ||
92 | check_assist( | ||
93 | flip_trait_bound, | ||
94 | "fn f<T>(t: T) where T: A <|>+ 'static { }", | ||
95 | "fn f<T>(t: T) where T: 'static <|>+ A { }", | ||
96 | ) | ||
97 | } | ||
98 | |||
99 | #[test] | ||
100 | fn flip_trait_bound_works_for_complex_bounds() { | ||
101 | check_assist( | ||
102 | flip_trait_bound, | ||
103 | "struct S<T> where T: A<T> <|>+ b_mod::B<T> + C<T> { }", | ||
104 | "struct S<T> where T: b_mod::B<T> <|>+ A<T> + C<T> { }", | ||
105 | ) | ||
106 | } | ||
107 | |||
108 | #[test] | ||
109 | fn flip_trait_bound_works_for_long_bounds() { | ||
110 | check_assist( | ||
111 | flip_trait_bound, | ||
112 | "struct S<T> where T: A + B + C + D + E + F +<|> G + H + I + J { }", | ||
113 | "struct S<T> where T: A + B + C + D + E + G +<|> F + H + I + J { }", | ||
114 | ) | ||
115 | } | ||
116 | } | ||