diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_assists/src/fill_match_arms.rs | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/crates/ra_assists/src/fill_match_arms.rs b/crates/ra_assists/src/fill_match_arms.rs index c7a8bce20..71b101b40 100644 --- a/crates/ra_assists/src/fill_match_arms.rs +++ b/crates/ra_assists/src/fill_match_arms.rs | |||
@@ -1,4 +1,5 @@ | |||
1 | use std::fmt::Write; | 1 | use std::fmt::Write; |
2 | use itertools::Itertools; | ||
2 | 3 | ||
3 | use hir::{ | 4 | use hir::{ |
4 | AdtDef, FieldSource, HasSource, | 5 | AdtDef, FieldSource, HasSource, |
@@ -8,13 +9,41 @@ use ra_syntax::ast::{self, AstNode}; | |||
8 | 9 | ||
9 | use crate::{AssistCtx, Assist, AssistId}; | 10 | use crate::{AssistCtx, Assist, AssistId}; |
10 | 11 | ||
12 | fn is_trivial_arm(arm: &ast::MatchArm) -> bool { | ||
13 | fn single_pattern(arm: &ast::MatchArm) -> Option<ast::PatKind> { | ||
14 | let (pat,) = arm.pats().collect_tuple()?; | ||
15 | Some(pat.kind()) | ||
16 | } | ||
17 | match single_pattern(arm) { | ||
18 | Some(ast::PatKind::PlaceholderPat(..)) => true, | ||
19 | _ => false, | ||
20 | } | ||
21 | } | ||
22 | |||
11 | pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { | 23 | pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { |
12 | let match_expr = ctx.node_at_offset::<ast::MatchExpr>()?; | 24 | let match_expr = ctx.node_at_offset::<ast::MatchExpr>()?; |
13 | 25 | ||
14 | // We already have some match arms, so we don't provide any assists. | 26 | // We already have some match arms, so we don't provide any assists. |
27 | // Unless if there is only one trivial match arm possibly created | ||
28 | // by match postfix complete. Trivial match arm is the catch all arm. | ||
15 | match match_expr.match_arm_list() { | 29 | match match_expr.match_arm_list() { |
16 | Some(arm_list) if arm_list.arms().count() > 0 => { | 30 | Some(arm_list) => { |
17 | return None; | 31 | let mut arm_iter = arm_list.arms(); |
32 | let first = arm_iter.next(); | ||
33 | |||
34 | match first { | ||
35 | // If there arm list is empty or there is only one trivial arm, then proceed. | ||
36 | Some(arm) if is_trivial_arm(arm) => { | ||
37 | if arm_iter.next() != None { | ||
38 | return None; | ||
39 | } | ||
40 | } | ||
41 | None => {} | ||
42 | |||
43 | _ => { | ||
44 | return None; | ||
45 | } | ||
46 | } | ||
18 | } | 47 | } |
19 | _ => {} | 48 | _ => {} |
20 | } | 49 | } |
@@ -228,4 +257,30 @@ mod tests { | |||
228 | "match E::X {}", | 257 | "match E::X {}", |
229 | ); | 258 | ); |
230 | } | 259 | } |
260 | |||
261 | #[test] | ||
262 | fn fill_match_arms_trivial_arm() { | ||
263 | check_assist( | ||
264 | fill_match_arms, | ||
265 | r#" | ||
266 | enum E { X, Y } | ||
267 | |||
268 | fn main() { | ||
269 | match E::X { | ||
270 | <|>_ => {}, | ||
271 | } | ||
272 | } | ||
273 | "#, | ||
274 | r#" | ||
275 | enum E { X, Y } | ||
276 | |||
277 | fn main() { | ||
278 | match <|>E::X { | ||
279 | E::X => (), | ||
280 | E::Y => (), | ||
281 | } | ||
282 | } | ||
283 | "#, | ||
284 | ); | ||
285 | } | ||
231 | } | 286 | } |