@@ -53,7 +53,7 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option<
53
53
. iter ( )
54
54
. filter_map ( ast:: MatchArm :: pat)
55
55
. flat_map ( |pat| match pat {
56
- // Special casee OrPat as separate top-level pats
56
+ // Special case OrPat as separate top-level pats
57
57
Pat :: OrPat ( or_pat) => Either :: Left ( or_pat. pats ( ) ) ,
58
58
_ => Either :: Right ( iter:: once ( pat) ) ,
59
59
} )
@@ -72,7 +72,11 @@ pub(crate) fn fill_match_arms(acc: &mut Assists, ctx: &AssistContext) -> Option<
72
72
. filter ( |variant_pat| is_variant_missing ( & top_lvl_pats, variant_pat) )
73
73
. map ( |pat| make:: match_arm ( iter:: once ( pat) , make:: expr_empty_block ( ) ) )
74
74
. collect :: < Vec < _ > > ( ) ;
75
- if Some ( enum_def) == FamousDefs ( & ctx. sema , Some ( module. krate ( ) ) ) . core_option_Option ( ) {
75
+ if Some ( enum_def)
76
+ == FamousDefs ( & ctx. sema , Some ( module. krate ( ) ) )
77
+ . core_option_Option ( )
78
+ . map ( |x| lift_enum ( x) )
79
+ {
76
80
// Match `Some` variant first.
77
81
cov_mark:: hit!( option_order) ;
78
82
variants. reverse ( )
@@ -151,49 +155,99 @@ fn does_pat_match_variant(pat: &Pat, var: &Pat) -> bool {
151
155
}
152
156
}
153
157
154
- fn resolve_enum_def ( sema : & Semantics < RootDatabase > , expr : & ast:: Expr ) -> Option < hir:: Enum > {
158
+ #[ derive( Eq , PartialEq , Clone ) ]
159
+ enum ExtendedEnum {
160
+ Bool ,
161
+ Enum ( hir:: Enum ) ,
162
+ }
163
+
164
+ #[ derive( Eq , PartialEq , Clone ) ]
165
+ enum ExtendedVariant {
166
+ True ,
167
+ False ,
168
+ Variant ( hir:: Variant ) ,
169
+ }
170
+
171
+ fn lift_enum ( e : hir:: Enum ) -> ExtendedEnum {
172
+ ExtendedEnum :: Enum ( e)
173
+ }
174
+
175
+ impl ExtendedEnum {
176
+ fn variants ( & self , db : & RootDatabase ) -> Vec < ExtendedVariant > {
177
+ match self {
178
+ ExtendedEnum :: Enum ( e) => {
179
+ e. variants ( db) . into_iter ( ) . map ( |x| ExtendedVariant :: Variant ( x) ) . collect :: < Vec < _ > > ( )
180
+ }
181
+ ExtendedEnum :: Bool => {
182
+ Vec :: < ExtendedVariant > :: from ( [ ExtendedVariant :: True , ExtendedVariant :: False ] )
183
+ }
184
+ }
185
+ }
186
+ }
187
+
188
+ fn resolve_enum_def ( sema : & Semantics < RootDatabase > , expr : & ast:: Expr ) -> Option < ExtendedEnum > {
155
189
sema. type_of_expr ( & expr) ?. autoderef ( sema. db ) . find_map ( |ty| match ty. as_adt ( ) {
156
- Some ( Adt :: Enum ( e) ) => Some ( e) ,
157
- _ => None ,
190
+ Some ( Adt :: Enum ( e) ) => Some ( ExtendedEnum :: Enum ( e) ) ,
191
+ _ => {
192
+ if ty. is_bool ( ) {
193
+ Some ( ExtendedEnum :: Bool )
194
+ } else {
195
+ None
196
+ }
197
+ }
158
198
} )
159
199
}
160
200
161
201
fn resolve_tuple_of_enum_def (
162
202
sema : & Semantics < RootDatabase > ,
163
203
expr : & ast:: Expr ,
164
- ) -> Option < Vec < hir :: Enum > > {
204
+ ) -> Option < Vec < ExtendedEnum > > {
165
205
sema. type_of_expr ( & expr) ?
166
206
. tuple_fields ( sema. db )
167
207
. iter ( )
168
208
. map ( |ty| {
169
209
ty. autoderef ( sema. db ) . find_map ( |ty| match ty. as_adt ( ) {
170
- Some ( Adt :: Enum ( e) ) => Some ( e ) ,
210
+ Some ( Adt :: Enum ( e) ) => Some ( lift_enum ( e ) ) ,
171
211
// For now we only handle expansion for a tuple of enums. Here
172
212
// we map non-enum items to None and rely on `collect` to
173
213
// convert Vec<Option<hir::Enum>> into Option<Vec<hir::Enum>>.
174
- _ => None ,
214
+ _ => {
215
+ if ty. is_bool ( ) {
216
+ Some ( ExtendedEnum :: Bool )
217
+ } else {
218
+ None
219
+ }
220
+ }
175
221
} )
176
222
} )
177
223
. collect ( )
178
224
}
179
225
180
- fn build_pat ( db : & RootDatabase , module : hir:: Module , var : hir:: Variant ) -> Option < ast:: Pat > {
181
- let path = mod_path_to_ast ( & module. find_use_path ( db, ModuleDef :: from ( var) ) ?) ;
226
+ fn build_pat ( db : & RootDatabase , module : hir:: Module , var : ExtendedVariant ) -> Option < ast:: Pat > {
227
+ match var {
228
+ ExtendedVariant :: Variant ( var) => {
229
+ let path = mod_path_to_ast ( & module. find_use_path ( db, ModuleDef :: from ( var) ) ?) ;
230
+
231
+ // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though
232
+ let pat: ast:: Pat = match var. source ( db) ?. value . kind ( ) {
233
+ ast:: StructKind :: Tuple ( field_list) => {
234
+ let pats =
235
+ iter:: repeat ( make:: wildcard_pat ( ) . into ( ) ) . take ( field_list. fields ( ) . count ( ) ) ;
236
+ make:: tuple_struct_pat ( path, pats) . into ( )
237
+ }
238
+ ast:: StructKind :: Record ( field_list) => {
239
+ let pats =
240
+ field_list. fields ( ) . map ( |f| make:: ident_pat ( f. name ( ) . unwrap ( ) ) . into ( ) ) ;
241
+ make:: record_pat ( path, pats) . into ( )
242
+ }
243
+ ast:: StructKind :: Unit => make:: path_pat ( path) ,
244
+ } ;
182
245
183
- // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though
184
- let pat: ast:: Pat = match var. source ( db) ?. value . kind ( ) {
185
- ast:: StructKind :: Tuple ( field_list) => {
186
- let pats = iter:: repeat ( make:: wildcard_pat ( ) . into ( ) ) . take ( field_list. fields ( ) . count ( ) ) ;
187
- make:: tuple_struct_pat ( path, pats) . into ( )
188
- }
189
- ast:: StructKind :: Record ( field_list) => {
190
- let pats = field_list. fields ( ) . map ( |f| make:: ident_pat ( f. name ( ) . unwrap ( ) ) . into ( ) ) ;
191
- make:: record_pat ( path, pats) . into ( )
246
+ Some ( pat)
192
247
}
193
- ast:: StructKind :: Unit => make:: path_pat ( path) ,
194
- } ;
195
-
196
- Some ( pat)
248
+ ExtendedVariant :: True => Some ( ast:: Pat :: from ( make:: literal_pat ( "true" ) ) ) ,
249
+ ExtendedVariant :: False => Some ( ast:: Pat :: from ( make:: literal_pat ( "false" ) ) ) ,
250
+ }
197
251
}
198
252
199
253
#[ cfg( test) ]
@@ -225,6 +279,21 @@ mod tests {
225
279
) ;
226
280
}
227
281
282
+ #[ test]
283
+ fn all_boolean_match_arms_provided ( ) {
284
+ check_assist_not_applicable (
285
+ fill_match_arms,
286
+ r#"
287
+ fn foo(a: bool) {
288
+ match a$0 {
289
+ true => {}
290
+ false => {}
291
+ }
292
+ }
293
+ "# ,
294
+ )
295
+ }
296
+
228
297
#[ test]
229
298
fn tuple_of_non_enum ( ) {
230
299
// for now this case is not handled, although it potentially could be
@@ -240,6 +309,113 @@ mod tests {
240
309
) ;
241
310
}
242
311
312
+ #[ test]
313
+ fn fill_match_arms_boolean ( ) {
314
+ check_assist (
315
+ fill_match_arms,
316
+ r#"
317
+ fn foo(a: bool) {
318
+ match a$0 {
319
+ }
320
+ }
321
+ "# ,
322
+ r#"
323
+ fn foo(a: bool) {
324
+ match a {
325
+ $0true => {}
326
+ false => {}
327
+ }
328
+ }
329
+ "# ,
330
+ )
331
+ }
332
+
333
+ #[ test]
334
+ fn partial_fill_boolean ( ) {
335
+ check_assist (
336
+ fill_match_arms,
337
+ r#"
338
+ fn foo(a: bool) {
339
+ match a$0 {
340
+ true => {}
341
+ }
342
+ }
343
+ "# ,
344
+ r#"
345
+ fn foo(a: bool) {
346
+ match a {
347
+ true => {}
348
+ $0false => {}
349
+ }
350
+ }
351
+ "# ,
352
+ )
353
+ }
354
+
355
+ #[ test]
356
+ fn all_boolean_tuple_arms_provided ( ) {
357
+ check_assist_not_applicable (
358
+ fill_match_arms,
359
+ r#"
360
+ fn foo(a: bool) {
361
+ match (a, a)$0 {
362
+ (true, true) => {}
363
+ (true, false) => {}
364
+ (false, true) => {}
365
+ (false, false) => {}
366
+ }
367
+ }
368
+ "# ,
369
+ )
370
+ }
371
+
372
+ #[ test]
373
+ fn fill_boolean_tuple ( ) {
374
+ check_assist (
375
+ fill_match_arms,
376
+ r#"
377
+ fn foo(a: bool) {
378
+ match (a, a)$0 {
379
+ }
380
+ }
381
+ "# ,
382
+ r#"
383
+ fn foo(a: bool) {
384
+ match (a, a) {
385
+ $0(true, true) => {}
386
+ (true, false) => {}
387
+ (false, true) => {}
388
+ (false, false) => {}
389
+ }
390
+ }
391
+ "# ,
392
+ )
393
+ }
394
+
395
+ #[ test]
396
+ fn partial_fill_boolean_tuple ( ) {
397
+ check_assist (
398
+ fill_match_arms,
399
+ r#"
400
+ fn foo(a: bool) {
401
+ match (a, a)$0 {
402
+ (false, true) => {}
403
+ }
404
+ }
405
+ "# ,
406
+ r#"
407
+ fn foo(a: bool) {
408
+ match (a, a) {
409
+ (false, true) => {}
410
+ $0(true, true) => {}
411
+ (true, false) => {}
412
+ (false, false) => {}
413
+ }
414
+ }
415
+ "# ,
416
+ )
417
+ }
418
+
243
419
#[ test]
244
420
fn partial_fill_record_tuple ( ) {
245
421
check_assist (
0 commit comments