|
1 | 1 | use std::iter::{self, successors};
|
2 | 2 |
|
3 | 3 | use either::Either;
|
4 |
| -use ide_db::{ty_filter::TryEnum, RootDatabase}; |
| 4 | +use ide_db::{defs::NameClass, ty_filter::TryEnum, RootDatabase}; |
5 | 5 | use syntax::{
|
6 | 6 | ast::{
|
7 | 7 | self,
|
8 | 8 | edit::{AstNodeEdit, IndentLevel},
|
9 |
| - make, |
| 9 | + make, NameOwner, |
10 | 10 | },
|
11 | 11 | AstNode,
|
12 | 12 | };
|
@@ -235,22 +235,34 @@ fn pick_pattern_and_expr_order(
|
235 | 235 | ) -> Option<(ast::Pat, ast::Expr, ast::Expr)> {
|
236 | 236 | let res = match (pat, pat2) {
|
237 | 237 | (ast::Pat::WildcardPat(_), _) => return None,
|
238 |
| - (pat, sad_pat) if is_sad_pat(sema, &sad_pat) => (pat, expr, expr2), |
239 |
| - (sad_pat, pat) if is_sad_pat(sema, &sad_pat) => (pat, expr2, expr), |
240 |
| - (pat, pat2) => match (binds_name(&pat), binds_name(&pat2)) { |
| 238 | + (pat, _) if is_empty_expr(&expr2) => (pat, expr, expr2), |
| 239 | + (_, pat) if is_empty_expr(&expr) => (pat, expr2, expr), |
| 240 | + (pat, pat2) => match (binds_name(sema, &pat), binds_name(sema, &pat2)) { |
241 | 241 | (true, true) => return None,
|
242 | 242 | (true, false) => (pat, expr, expr2),
|
243 | 243 | (false, true) => (pat2, expr2, expr),
|
| 244 | + _ if is_sad_pat(sema, &pat) => (pat2, expr2, expr), |
244 | 245 | (false, false) => (pat, expr, expr2),
|
245 | 246 | },
|
246 | 247 | };
|
247 | 248 | Some(res)
|
248 | 249 | }
|
249 | 250 |
|
250 |
| -fn binds_name(pat: &ast::Pat) -> bool { |
251 |
| - let binds_name_v = |pat| binds_name(&pat); |
| 251 | +fn is_empty_expr(expr: &ast::Expr) -> bool { |
| 252 | + match expr { |
| 253 | + ast::Expr::BlockExpr(expr) => expr.is_empty(), |
| 254 | + ast::Expr::TupleExpr(expr) => expr.fields().next().is_none(), |
| 255 | + _ => false, |
| 256 | + } |
| 257 | +} |
| 258 | + |
| 259 | +fn binds_name(sema: &hir::Semantics<RootDatabase>, pat: &ast::Pat) -> bool { |
| 260 | + let binds_name_v = |pat| binds_name(&sema, &pat); |
252 | 261 | match pat {
|
253 |
| - ast::Pat::IdentPat(_) => true, |
| 262 | + ast::Pat::IdentPat(pat) => !matches!( |
| 263 | + pat.name().and_then(|name| NameClass::classify(sema, &name)), |
| 264 | + Some(NameClass::ConstReference(_)) |
| 265 | + ), |
254 | 266 | ast::Pat::MacroPat(_) => true,
|
255 | 267 | ast::Pat::OrPat(pat) => pat.pats().any(binds_name_v),
|
256 | 268 | ast::Pat::SlicePat(pat) => pat.pats().any(binds_name_v),
|
@@ -702,6 +714,28 @@ fn main() {
|
702 | 714 | )
|
703 | 715 | }
|
704 | 716 |
|
| 717 | + #[test] |
| 718 | + fn replace_match_with_if_let_number_body() { |
| 719 | + check_assist( |
| 720 | + replace_match_with_if_let, |
| 721 | + r#" |
| 722 | +fn main() { |
| 723 | + $0match Ok(()) { |
| 724 | + Ok(()) => {}, |
| 725 | + Err(_) => 0, |
| 726 | + } |
| 727 | +} |
| 728 | +"#, |
| 729 | + r#" |
| 730 | +fn main() { |
| 731 | + if let Err(_) = Ok(()) { |
| 732 | + 0 |
| 733 | + } |
| 734 | +} |
| 735 | +"#, |
| 736 | + ) |
| 737 | + } |
| 738 | + |
705 | 739 | #[test]
|
706 | 740 | fn replace_match_with_if_let_exhaustive() {
|
707 | 741 | check_assist(
|
@@ -762,6 +796,46 @@ fn foo() {
|
762 | 796 | );
|
763 | 797 | }
|
764 | 798 |
|
| 799 | + #[test] |
| 800 | + fn replace_match_with_if_let_prefer_nonempty_body() { |
| 801 | + check_assist( |
| 802 | + replace_match_with_if_let, |
| 803 | + r#" |
| 804 | +fn foo() { |
| 805 | + match $0Ok(0) { |
| 806 | + Ok(value) => {}, |
| 807 | + Err(err) => eprintln!("{}", err), |
| 808 | + } |
| 809 | +} |
| 810 | +"#, |
| 811 | + r#" |
| 812 | +fn foo() { |
| 813 | + if let Err(err) = Ok(0) { |
| 814 | + eprintln!("{}", err) |
| 815 | + } |
| 816 | +} |
| 817 | +"#, |
| 818 | + ); |
| 819 | + check_assist( |
| 820 | + replace_match_with_if_let, |
| 821 | + r#" |
| 822 | +fn foo() { |
| 823 | + match $0Ok(0) { |
| 824 | + Err(err) => eprintln!("{}", err), |
| 825 | + Ok(value) => {}, |
| 826 | + } |
| 827 | +} |
| 828 | +"#, |
| 829 | + r#" |
| 830 | +fn foo() { |
| 831 | + if let Err(err) = Ok(0) { |
| 832 | + eprintln!("{}", err) |
| 833 | + } |
| 834 | +} |
| 835 | +"#, |
| 836 | + ); |
| 837 | + } |
| 838 | + |
765 | 839 | #[test]
|
766 | 840 | fn replace_match_with_if_let_rejects_double_name_bindings() {
|
767 | 841 | check_assist_not_applicable(
|
|
0 commit comments