1432: Make fill_match_arm work with trivial arm r=matklad a=ironyman

Addresses this issue https://github.com/rust-analyzer/rust-analyzer/issues/1399

One minor issue I noticed is that complete_postfix creates an arm like this

```
                match E::X {
                    <|>_ => {},
                }
```

but fill_match_arms creates arms like this
```
                     E::X => (), 
```

Co-authored-by: ironyman <ironyman@users.noreply.github.com>
Co-authored-by: Changyu Li <changyl@microsoft.com>
This commit is contained in:
bors[bot] 2019-06-25 21:06:17 +00:00
commit 0129790a8f

View File

@ -1,4 +1,5 @@
use std::fmt::Write;
use itertools::Itertools;
use hir::{
AdtDef, FieldSource, HasSource,
@ -8,13 +9,41 @@ use ra_syntax::ast::{self, AstNode};
use crate::{AssistCtx, Assist, AssistId};
fn is_trivial_arm(arm: &ast::MatchArm) -> bool {
fn single_pattern(arm: &ast::MatchArm) -> Option<ast::PatKind> {
let (pat,) = arm.pats().collect_tuple()?;
Some(pat.kind())
}
match single_pattern(arm) {
Some(ast::PatKind::PlaceholderPat(..)) => true,
_ => false,
}
}
pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
let match_expr = ctx.node_at_offset::<ast::MatchExpr>()?;
// We already have some match arms, so we don't provide any assists.
// Unless if there is only one trivial match arm possibly created
// by match postfix complete. Trivial match arm is the catch all arm.
match match_expr.match_arm_list() {
Some(arm_list) if arm_list.arms().count() > 0 => {
return None;
Some(arm_list) => {
let mut arm_iter = arm_list.arms();
let first = arm_iter.next();
match first {
// If there arm list is empty or there is only one trivial arm, then proceed.
Some(arm) if is_trivial_arm(arm) => {
if arm_iter.next() != None {
return None;
}
}
None => {}
_ => {
return None;
}
}
}
_ => {}
}
@ -228,4 +257,30 @@ mod tests {
"match E::X {}",
);
}
#[test]
fn fill_match_arms_trivial_arm() {
check_assist(
fill_match_arms,
r#"
enum E { X, Y }
fn main() {
match E::X {
<|>_ => {},
}
}
"#,
r#"
enum E { X, Y }
fn main() {
match <|>E::X {
E::X => (),
E::Y => (),
}
}
"#,
);
}
}