diff options
Diffstat (limited to 'crates/ra_assists')
-rw-r--r-- | crates/ra_assists/src/assists/flip_trait_bound.rs | 119 | ||||
-rw-r--r-- | crates/ra_assists/src/doc_tests.rs | 12 | ||||
-rw-r--r-- | crates/ra_assists/src/doc_tests/generated.rs | 13 | ||||
-rw-r--r-- | crates/ra_assists/src/lib.rs | 2 |
4 files changed, 145 insertions, 1 deletions
diff --git a/crates/ra_assists/src/assists/flip_trait_bound.rs b/crates/ra_assists/src/assists/flip_trait_bound.rs new file mode 100644 index 000000000..1625b241f --- /dev/null +++ b/crates/ra_assists/src/assists/flip_trait_bound.rs | |||
@@ -0,0 +1,119 @@ | |||
1 | use hir::db::HirDatabase; | ||
2 | use ra_syntax::{ | ||
3 | algo::non_trivia_sibling, | ||
4 | ast::{self, AstNode}, | ||
5 | Direction, T, | ||
6 | }; | ||
7 | |||
8 | use crate::{Assist, AssistCtx, AssistId}; | ||
9 | |||
10 | // Assist: flip_trait_bound | ||
11 | // | ||
12 | // Flips two trait bounds. | ||
13 | // | ||
14 | // ``` | ||
15 | // fn foo<T: Clone +<|> Copy>() { } | ||
16 | // ``` | ||
17 | // -> | ||
18 | // ``` | ||
19 | // fn foo<T: Copy + Clone>() { } | ||
20 | // ``` | ||
21 | pub(crate) fn flip_trait_bound(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | ||
22 | // We want to replicate the behavior of `flip_binexpr` by only suggesting | ||
23 | // the assist when the cursor is on a `+` | ||
24 | let plus = ctx.find_token_at_offset(T![+])?; | ||
25 | |||
26 | // Make sure we're in a `TypeBoundList` | ||
27 | if ast::TypeBoundList::cast(plus.parent()).is_none() { | ||
28 | return None; | ||
29 | } | ||
30 | |||
31 | let (before, after) = ( | ||
32 | non_trivia_sibling(plus.clone().into(), Direction::Prev)?, | ||
33 | non_trivia_sibling(plus.clone().into(), Direction::Next)?, | ||
34 | ); | ||
35 | |||
36 | ctx.add_action(AssistId("flip_trait_bound"), "flip trait bound", |edit| { | ||
37 | edit.target(plus.text_range()); | ||
38 | edit.replace(before.text_range(), after.to_string()); | ||
39 | edit.replace(after.text_range(), before.to_string()); | ||
40 | }); | ||
41 | |||
42 | ctx.build() | ||
43 | } | ||
44 | |||
45 | #[cfg(test)] | ||
46 | mod tests { | ||
47 | use super::*; | ||
48 | |||
49 | use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; | ||
50 | |||
51 | #[test] | ||
52 | fn flip_trait_bound_assist_available() { | ||
53 | check_assist_target(flip_trait_bound, "struct S<T> where T: A <|>+ B + C { }", "+") | ||
54 | } | ||
55 | |||
56 | #[test] | ||
57 | fn flip_trait_bound_not_applicable_for_single_trait_bound() { | ||
58 | check_assist_not_applicable(flip_trait_bound, "struct S<T> where T: <|>A { }") | ||
59 | } | ||
60 | |||
61 | #[test] | ||
62 | fn flip_trait_bound_works_for_struct() { | ||
63 | check_assist( | ||
64 | flip_trait_bound, | ||
65 | "struct S<T> where T: A <|>+ B { }", | ||
66 | "struct S<T> where T: B <|>+ A { }", | ||
67 | ) | ||
68 | } | ||
69 | |||
70 | #[test] | ||
71 | fn flip_trait_bound_works_for_trait_impl() { | ||
72 | check_assist( | ||
73 | flip_trait_bound, | ||
74 | "impl X for S<T> where T: A +<|> B { }", | ||
75 | "impl X for S<T> where T: B +<|> A { }", | ||
76 | ) | ||
77 | } | ||
78 | |||
79 | #[test] | ||
80 | fn flip_trait_bound_works_for_fn() { | ||
81 | check_assist(flip_trait_bound, "fn f<T: A <|>+ B>(t: T) { }", "fn f<T: B <|>+ A>(t: T) { }") | ||
82 | } | ||
83 | |||
84 | #[test] | ||
85 | fn flip_trait_bound_works_for_fn_where_clause() { | ||
86 | check_assist( | ||
87 | flip_trait_bound, | ||
88 | "fn f<T>(t: T) where T: A +<|> B { }", | ||
89 | "fn f<T>(t: T) where T: B +<|> A { }", | ||
90 | ) | ||
91 | } | ||
92 | |||
93 | #[test] | ||
94 | fn flip_trait_bound_works_for_lifetime() { | ||
95 | check_assist( | ||
96 | flip_trait_bound, | ||
97 | "fn f<T>(t: T) where T: A <|>+ 'static { }", | ||
98 | "fn f<T>(t: T) where T: 'static <|>+ A { }", | ||
99 | ) | ||
100 | } | ||
101 | |||
102 | #[test] | ||
103 | fn flip_trait_bound_works_for_complex_bounds() { | ||
104 | check_assist( | ||
105 | flip_trait_bound, | ||
106 | "struct S<T> where T: A<T> <|>+ b_mod::B<T> + C<T> { }", | ||
107 | "struct S<T> where T: b_mod::B<T> <|>+ A<T> + C<T> { }", | ||
108 | ) | ||
109 | } | ||
110 | |||
111 | #[test] | ||
112 | fn flip_trait_bound_works_for_long_bounds() { | ||
113 | check_assist( | ||
114 | flip_trait_bound, | ||
115 | "struct S<T> where T: A + B + C + D + E + F +<|> G + H + I + J { }", | ||
116 | "struct S<T> where T: A + B + C + D + E + G +<|> F + H + I + J { }", | ||
117 | ) | ||
118 | } | ||
119 | } | ||
diff --git a/crates/ra_assists/src/doc_tests.rs b/crates/ra_assists/src/doc_tests.rs index 0ccf9d730..6e1e3de84 100644 --- a/crates/ra_assists/src/doc_tests.rs +++ b/crates/ra_assists/src/doc_tests.rs | |||
@@ -17,7 +17,17 @@ fn check(assist_id: &str, before: &str, after: &str) { | |||
17 | let (_assist_id, action) = crate::assists(&db, frange) | 17 | let (_assist_id, action) = crate::assists(&db, frange) |
18 | .into_iter() | 18 | .into_iter() |
19 | .find(|(id, _)| id.id.0 == assist_id) | 19 | .find(|(id, _)| id.id.0 == assist_id) |
20 | .unwrap_or_else(|| panic!("Assist {:?} is not applicable", assist_id)); | 20 | .unwrap_or_else(|| { |
21 | panic!( | ||
22 | "\n\nAssist is not applicable: {}\nAvailable assists: {}", | ||
23 | assist_id, | ||
24 | crate::assists(&db, frange) | ||
25 | .into_iter() | ||
26 | .map(|(id, _)| id.id.0) | ||
27 | .collect::<Vec<_>>() | ||
28 | .join(", ") | ||
29 | ) | ||
30 | }); | ||
21 | 31 | ||
22 | let actual = action.edit.apply(&before); | 32 | let actual = action.edit.apply(&before); |
23 | assert_eq_text!(after, &actual); | 33 | assert_eq_text!(after, &actual); |
diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs index b8d335911..ebe49aecf 100644 --- a/crates/ra_assists/src/doc_tests/generated.rs +++ b/crates/ra_assists/src/doc_tests/generated.rs | |||
@@ -256,6 +256,19 @@ fn main() { | |||
256 | } | 256 | } |
257 | 257 | ||
258 | #[test] | 258 | #[test] |
259 | fn doctest_flip_trait_bound() { | ||
260 | check( | ||
261 | "flip_trait_bound", | ||
262 | r#####" | ||
263 | fn foo<T: Clone +<|> Copy>() { } | ||
264 | "#####, | ||
265 | r#####" | ||
266 | fn foo<T: Copy + Clone>() { } | ||
267 | "#####, | ||
268 | ) | ||
269 | } | ||
270 | |||
271 | #[test] | ||
259 | fn doctest_inline_local_variable() { | 272 | fn doctest_inline_local_variable() { |
260 | check( | 273 | check( |
261 | "inline_local_variable", | 274 | "inline_local_variable", |
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 7c226572a..7a1657d87 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -97,6 +97,7 @@ mod assists { | |||
97 | mod apply_demorgan; | 97 | mod apply_demorgan; |
98 | mod flip_comma; | 98 | mod flip_comma; |
99 | mod flip_binexpr; | 99 | mod flip_binexpr; |
100 | mod flip_trait_bound; | ||
100 | mod change_visibility; | 101 | mod change_visibility; |
101 | mod fill_match_arms; | 102 | mod fill_match_arms; |
102 | mod merge_match_arms; | 103 | mod merge_match_arms; |
@@ -123,6 +124,7 @@ mod assists { | |||
123 | merge_match_arms::merge_match_arms, | 124 | merge_match_arms::merge_match_arms, |
124 | flip_comma::flip_comma, | 125 | flip_comma::flip_comma, |
125 | flip_binexpr::flip_binexpr, | 126 | flip_binexpr::flip_binexpr, |
127 | flip_trait_bound::flip_trait_bound, | ||
126 | introduce_variable::introduce_variable, | 128 | introduce_variable::introduce_variable, |
127 | replace_if_let_with_match::replace_if_let_with_match, | 129 | replace_if_let_with_match::replace_if_let_with_match, |
128 | split_import::split_import, | 130 | split_import::split_import, |