11//! Module responsible for analyzing the code surrounding the cursor for completion.
22use std:: iter;
33
4- use hir:: { Semantics , Type , TypeInfo } ;
4+ use hir:: { Semantics , Type , TypeInfo , Variant } ;
55use ide_db:: { active_parameter:: ActiveParameter , RootDatabase } ;
66use syntax:: {
77 algo:: { find_node_at_offset, non_trivia_sibling} ,
@@ -1111,6 +1111,9 @@ fn pattern_context_for(
11111111 pat : ast:: Pat ,
11121112) -> PatternContext {
11131113 let mut param_ctx = None ;
1114+
1115+ let mut missing_variants = vec ! [ ] ;
1116+
11141117 let ( refutability, has_type_ascription) =
11151118 pat
11161119 . syntax ( )
@@ -1140,7 +1143,52 @@ fn pattern_context_for(
11401143 } ) ( ) ;
11411144 return ( PatternRefutability :: Irrefutable , has_type_ascription)
11421145 } ,
1143- ast:: MatchArm ( _) => PatternRefutability :: Refutable ,
1146+ ast:: MatchArm ( match_arm) => {
1147+ let missing_variants_opt = match_arm
1148+ . syntax( )
1149+ . parent( )
1150+ . and_then( ast:: MatchArmList :: cast)
1151+ . and_then( |match_arm_list| {
1152+ match_arm_list
1153+ . syntax( )
1154+ . parent( )
1155+ . and_then( ast:: MatchExpr :: cast)
1156+ . and_then( |match_expr| {
1157+ let expr_opt = find_opt_node_in_file( & original_file, match_expr. expr( ) ) ;
1158+
1159+ expr_opt. and_then( |expr| {
1160+ sema. type_of_expr( & expr) ?
1161+ . adjusted( )
1162+ . autoderef( sema. db)
1163+ . find_map( |ty| match ty. as_adt( ) {
1164+ Some ( hir:: Adt :: Enum ( e) ) => Some ( e) ,
1165+ _ => None ,
1166+ } ) . and_then( |enum_| {
1167+ Some ( enum_. variants( sema. db) )
1168+ } )
1169+ } )
1170+ } ) . and_then( |variants| {
1171+ Some ( variants. iter( ) . filter_map( |variant| {
1172+ let variant_name = variant. name( sema. db) . to_string( ) ;
1173+
1174+ let variant_already_present = match_arm_list. arms( ) . any( |arm| {
1175+ arm. pat( ) . and_then( |pat| {
1176+ let pat_already_present = pat. syntax( ) . to_string( ) . contains( & variant_name) ;
1177+ pat_already_present. then( || pat_already_present)
1178+ } ) . is_some( )
1179+ } ) ;
1180+
1181+ ( !variant_already_present) . then_some( variant. clone( ) )
1182+ } ) . collect:: <Vec <Variant >>( ) )
1183+ } )
1184+ } ) ;
1185+
1186+ if let Some ( missing_variants_) = missing_variants_opt {
1187+ missing_variants = missing_variants_;
1188+ } ;
1189+
1190+ PatternRefutability :: Refutable
1191+ } ,
11441192 ast:: LetExpr ( _) => PatternRefutability :: Refutable ,
11451193 ast:: ForExpr ( _) => PatternRefutability :: Irrefutable ,
11461194 _ => PatternRefutability :: Irrefutable ,
@@ -1162,6 +1210,7 @@ fn pattern_context_for(
11621210 ref_token,
11631211 record_pat : None ,
11641212 impl_ : fetch_immediate_impl ( sema, original_file, pat. syntax ( ) ) ,
1213+ missing_variants,
11651214 }
11661215}
11671216
0 commit comments