diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ide_assists/src/handlers/fill_match_arms.rs | 47 |
1 files changed, 24 insertions, 23 deletions
diff --git a/crates/ide_assists/src/handlers/fill_match_arms.rs b/crates/ide_assists/src/handlers/fill_match_arms.rs index 58b001050..12ea17d7a 100644 --- a/crates/ide_assists/src/handlers/fill_match_arms.rs +++ b/crates/ide_assists/src/handlers/fill_match_arms.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use std::iter; | 1 | use std::iter::{self, Peekable}; |
2 | 2 | ||
3 | use either::Either; | 3 | use either::Either; |
4 | use hir::{Adt, HasSource, ModuleDef, Semantics}; | 4 | use hir::{Adt, HasSource, ModuleDef, Semantics}; |
@@ -63,33 +63,33 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option< | |||
63 | 63 | ||
64 | let module = ctx.sema.scope(expr.syntax()).module()?; | 64 | let module = ctx.sema.scope(expr.syntax()).module()?; |
65 | 65 | ||
66 | let missing_arms: Vec<MatchArm> = if let Some(enum_def) = resolve_enum_def(&ctx.sema, &expr) { | 66 | let mut missing_pats: Peekable<Box<dyn Iterator<Item = ast::Pat>>> = if let Some(enum_def) = |
67 | resolve_enum_def(&ctx.sema, &expr) | ||
68 | { | ||
67 | let variants = enum_def.variants(ctx.db()); | 69 | let variants = enum_def.variants(ctx.db()); |
68 | 70 | ||
69 | let mut variants = variants | 71 | let missing_pats = variants |
70 | .into_iter() | 72 | .into_iter() |
71 | .filter_map(|variant| build_pat(ctx.db(), module, variant)) | 73 | .filter_map(|variant| build_pat(ctx.db(), module, variant)) |
72 | .filter(|variant_pat| is_variant_missing(&top_lvl_pats, variant_pat)) | 74 | .filter(|variant_pat| is_variant_missing(&top_lvl_pats, variant_pat)); |
73 | .map(|pat| make::match_arm(iter::once(pat), make::expr_empty_block())) | 75 | |
74 | .map(|it| it.clone_for_update()) | 76 | let missing_pats: Box<dyn Iterator<Item = _>> = if Some(enum_def) |
75 | .collect::<Vec<_>>(); | 77 | == FamousDefs(&ctx.sema, Some(module.krate())).core_option_Option().map(lift_enum) |
76 | if Some(enum_def) | ||
77 | == FamousDefs(&ctx.sema, Some(module.krate())) | ||
78 | .core_option_Option() | ||
79 | .map(|x| lift_enum(x)) | ||
80 | { | 78 | { |
81 | // Match `Some` variant first. | 79 | // Match `Some` variant first. |
82 | cov_mark::hit!(option_order); | 80 | cov_mark::hit!(option_order); |
83 | variants.reverse() | 81 | Box::new(missing_pats.rev()) |
84 | } | 82 | } else { |
85 | variants | 83 | Box::new(missing_pats) |
84 | }; | ||
85 | missing_pats.peekable() | ||
86 | } else if let Some(enum_defs) = resolve_tuple_of_enum_def(&ctx.sema, &expr) { | 86 | } else if let Some(enum_defs) = resolve_tuple_of_enum_def(&ctx.sema, &expr) { |
87 | // When calculating the match arms for a tuple of enums, we want | 87 | // When calculating the match arms for a tuple of enums, we want |
88 | // to create a match arm for each possible combination of enum | 88 | // to create a match arm for each possible combination of enum |
89 | // values. The `multi_cartesian_product` method transforms | 89 | // values. The `multi_cartesian_product` method transforms |
90 | // Vec<Vec<EnumVariant>> into Vec<(EnumVariant, .., EnumVariant)> | 90 | // Vec<Vec<EnumVariant>> into Vec<(EnumVariant, .., EnumVariant)> |
91 | // where each tuple represents a proposed match arm. | 91 | // where each tuple represents a proposed match arm. |
92 | enum_defs | 92 | let missing_pats = enum_defs |
93 | .into_iter() | 93 | .into_iter() |
94 | .map(|enum_def| enum_def.variants(ctx.db())) | 94 | .map(|enum_def| enum_def.variants(ctx.db())) |
95 | .multi_cartesian_product() | 95 | .multi_cartesian_product() |
@@ -98,15 +98,13 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option< | |||
98 | variants.into_iter().filter_map(|variant| build_pat(ctx.db(), module, variant)); | 98 | variants.into_iter().filter_map(|variant| build_pat(ctx.db(), module, variant)); |
99 | ast::Pat::from(make::tuple_pat(patterns)) | 99 | ast::Pat::from(make::tuple_pat(patterns)) |
100 | }) | 100 | }) |
101 | .filter(|variant_pat| is_variant_missing(&top_lvl_pats, variant_pat)) | 101 | .filter(|variant_pat| is_variant_missing(&top_lvl_pats, variant_pat)); |
102 | .map(|pat| make::match_arm(iter::once(pat), make::expr_empty_block())) | 102 | (Box::new(missing_pats) as Box<dyn Iterator<Item = _>>).peekable() |
103 | .map(|it| it.clone_for_update()) | ||
104 | .collect() | ||
105 | } else { | 103 | } else { |
106 | return None; | 104 | return None; |
107 | }; | 105 | }; |
108 | 106 | ||
109 | if missing_arms.is_empty() { | 107 | if missing_pats.peek().is_none() { |
110 | return None; | 108 | return None; |
111 | } | 109 | } |
112 | 110 | ||
@@ -117,6 +115,9 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option< | |||
117 | target, | 115 | target, |
118 | |builder| { | 116 | |builder| { |
119 | let new_match_arm_list = match_arm_list.clone_for_update(); | 117 | let new_match_arm_list = match_arm_list.clone_for_update(); |
118 | let missing_arms = missing_pats | ||
119 | .map(|pat| make::match_arm(iter::once(pat), make::expr_empty_block())) | ||
120 | .map(|it| it.clone_for_update()); | ||
120 | 121 | ||
121 | let catch_all_arm = new_match_arm_list | 122 | let catch_all_arm = new_match_arm_list |
122 | .arms() | 123 | .arms() |
@@ -167,13 +168,13 @@ fn does_pat_match_variant(pat: &Pat, var: &Pat) -> bool { | |||
167 | } | 168 | } |
168 | } | 169 | } |
169 | 170 | ||
170 | #[derive(Eq, PartialEq, Clone)] | 171 | #[derive(Eq, PartialEq, Clone, Copy)] |
171 | enum ExtendedEnum { | 172 | enum ExtendedEnum { |
172 | Bool, | 173 | Bool, |
173 | Enum(hir::Enum), | 174 | Enum(hir::Enum), |
174 | } | 175 | } |
175 | 176 | ||
176 | #[derive(Eq, PartialEq, Clone)] | 177 | #[derive(Eq, PartialEq, Clone, Copy)] |
177 | enum ExtendedVariant { | 178 | enum ExtendedVariant { |
178 | True, | 179 | True, |
179 | False, | 180 | False, |
@@ -185,7 +186,7 @@ fn lift_enum(e: hir::Enum) -> ExtendedEnum { | |||
185 | } | 186 | } |
186 | 187 | ||
187 | impl ExtendedEnum { | 188 | impl ExtendedEnum { |
188 | fn variants(&self, db: &RootDatabase) -> Vec<ExtendedVariant> { | 189 | fn variants(self, db: &RootDatabase) -> Vec<ExtendedVariant> { |
189 | match self { | 190 | match self { |
190 | ExtendedEnum::Enum(e) => { | 191 | ExtendedEnum::Enum(e) => { |
191 | e.variants(db).into_iter().map(|x| ExtendedVariant::Variant(x)).collect::<Vec<_>>() | 192 | e.variants(db).into_iter().map(|x| ExtendedVariant::Variant(x)).collect::<Vec<_>>() |