@@ -2,28 +2,12 @@ use hir::{PathResolution, StructKind};
22use ide_db:: syntax_helpers:: suggest_name:: NameGenerator ;
33use syntax:: {
44 AstNode , ToSmolStr ,
5- ast:: { self , make } ,
5+ ast:: { self , syntax_factory :: SyntaxFactory } ,
66 match_ast,
77} ;
88
99use crate :: { AssistContext , AssistId , Assists } ;
1010
11- pub ( crate ) fn expand_rest_pattern ( acc : & mut Assists , ctx : & AssistContext < ' _ > ) -> Option < ( ) > {
12- let rest_pat = ctx. find_node_at_offset :: < ast:: RestPat > ( ) ?;
13- let parent = rest_pat. syntax ( ) . parent ( ) ?;
14- match_ast ! {
15- match parent {
16- ast:: RecordPatFieldList ( it) => expand_record_rest_pattern( acc, ctx, it. syntax( ) . parent( ) . and_then( ast:: RecordPat :: cast) ?, rest_pat) ,
17- ast:: TupleStructPat ( it) => expand_tuple_struct_rest_pattern( acc, ctx, it, rest_pat) ,
18- // FIXME
19- // ast::TuplePat(it) => (),
20- // FIXME
21- // ast::SlicePat(it) => (),
22- _ => return None ,
23- }
24- }
25- }
26-
2711// Assist: expand_record_rest_pattern
2812//
2913// Fills fields by replacing rest pattern in record patterns.
@@ -50,7 +34,6 @@ fn expand_record_rest_pattern(
5034 rest_pat : ast:: RestPat ,
5135) -> Option < ( ) > {
5236 let missing_fields = ctx. sema . record_pattern_missing_fields ( & record_pat) ;
53-
5437 if missing_fields. is_empty ( ) {
5538 cov_mark:: hit!( no_missing_fields) ;
5639 return None ;
@@ -62,24 +45,30 @@ fn expand_record_rest_pattern(
6245 return None ;
6346 }
6447
65- let new_field_list =
66- make:: record_pat_field_list ( old_field_list. fields ( ) , None ) . clone_for_update ( ) ;
67- for ( f, _) in missing_fields. iter ( ) {
68- let edition = ctx. sema . scope ( record_pat. syntax ( ) ) ?. krate ( ) . edition ( ctx. db ( ) ) ;
69- let field = make:: record_pat_field_shorthand ( make:: name_ref (
70- & f. name ( ctx. sema . db ) . display_no_db ( edition) . to_smolstr ( ) ,
71- ) ) ;
72- new_field_list. add_field ( field. clone_for_update ( ) ) ;
73- }
74-
75- let target_range = rest_pat. syntax ( ) . text_range ( ) ;
48+ let edition = ctx. sema . scope ( record_pat. syntax ( ) ) ?. krate ( ) . edition ( ctx. db ( ) ) ;
7649 acc. add (
7750 AssistId :: refactor_rewrite ( "expand_record_rest_pattern" ) ,
7851 "Fill struct fields" ,
79- target_range,
80- move |builder| builder. replace_ast ( old_field_list, new_field_list) ,
52+ rest_pat. syntax ( ) . text_range ( ) ,
53+ |builder| {
54+ let make = SyntaxFactory :: with_mappings ( ) ;
55+ let mut editor = builder. make_editor ( rest_pat. syntax ( ) ) ;
56+ let new_field_list = make. record_pat_field_list ( old_field_list. fields ( ) , None ) ;
57+ for ( f, _) in missing_fields. iter ( ) {
58+ let field = make. record_pat_field_shorthand (
59+ make. name_ref ( & f. name ( ctx. sema . db ) . display_no_db ( edition) . to_smolstr ( ) ) ,
60+ ) ;
61+ new_field_list. add_field ( field) ;
62+ }
63+
64+ editor. replace ( old_field_list. syntax ( ) , new_field_list. syntax ( ) ) ;
65+
66+ editor. add_mappings ( make. finish_with_mappings ( ) ) ;
67+ builder. add_file_edits ( ctx. file_id ( ) , editor) ;
68+ } ,
8169 )
8270}
71+
8372// Assist: expand_tuple_struct_rest_pattern
8473//
8574// Fills fields by replacing rest pattern in tuple struct patterns.
@@ -134,34 +123,58 @@ fn expand_tuple_struct_rest_pattern(
134123 return None ;
135124 }
136125
137- let mut name_gen = NameGenerator :: new_from_scope_locals ( ctx. sema . scope ( pat. syntax ( ) ) ) ;
138- let new_pat = make:: tuple_struct_pat (
139- path,
140- pat. fields ( )
141- . take ( prefix_count)
142- . chain ( fields[ prefix_count..fields. len ( ) - suffix_count] . iter ( ) . map ( |f| {
143- make:: ident_pat (
144- false ,
145- false ,
146- match name_gen. for_type ( & f. ty ( ctx. sema . db ) , ctx. sema . db , ctx. edition ( ) ) {
147- Some ( name) => make:: name ( & name) ,
148- None => make:: name ( & format ! ( "_{}" , f. index( ) ) ) ,
149- } ,
150- )
151- . into ( )
152- } ) )
153- . chain ( pat. fields ( ) . skip ( prefix_count + 1 ) ) ,
154- ) ;
155-
156- let target_range = rest_pat. syntax ( ) . text_range ( ) ;
157126 acc. add (
158127 AssistId :: refactor_rewrite ( "expand_tuple_struct_rest_pattern" ) ,
159128 "Fill tuple struct fields" ,
160- target_range,
161- move |builder| builder. replace_ast ( pat, new_pat) ,
129+ rest_pat. syntax ( ) . text_range ( ) ,
130+ |builder| {
131+ let make = SyntaxFactory :: with_mappings ( ) ;
132+ let mut editor = builder. make_editor ( rest_pat. syntax ( ) ) ;
133+
134+ let mut name_gen = NameGenerator :: new_from_scope_locals ( ctx. sema . scope ( pat. syntax ( ) ) ) ;
135+ let new_pat = make. tuple_struct_pat (
136+ path,
137+ pat. fields ( )
138+ . take ( prefix_count)
139+ . chain ( fields[ prefix_count..fields. len ( ) - suffix_count] . iter ( ) . map ( |f| {
140+ make. ident_pat (
141+ false ,
142+ false ,
143+ match name_gen. for_type ( & f. ty ( ctx. sema . db ) , ctx. sema . db , ctx. edition ( ) )
144+ {
145+ Some ( name) => make. name ( & name) ,
146+ None => make. name ( & format ! ( "_{}" , f. index( ) ) ) ,
147+ } ,
148+ )
149+ . into ( )
150+ } ) )
151+ . chain ( pat. fields ( ) . skip ( prefix_count + 1 ) ) ,
152+ ) ;
153+
154+ editor. replace ( pat. syntax ( ) , new_pat. syntax ( ) ) ;
155+
156+ editor. add_mappings ( make. finish_with_mappings ( ) ) ;
157+ builder. add_file_edits ( ctx. file_id ( ) , editor) ;
158+ } ,
162159 )
163160}
164161
162+ pub ( crate ) fn expand_rest_pattern ( acc : & mut Assists , ctx : & AssistContext < ' _ > ) -> Option < ( ) > {
163+ let rest_pat = ctx. find_node_at_offset :: < ast:: RestPat > ( ) ?;
164+ let parent = rest_pat. syntax ( ) . parent ( ) ?;
165+ match_ast ! {
166+ match parent {
167+ ast:: RecordPatFieldList ( it) => expand_record_rest_pattern( acc, ctx, it. syntax( ) . parent( ) . and_then( ast:: RecordPat :: cast) ?, rest_pat) ,
168+ ast:: TupleStructPat ( it) => expand_tuple_struct_rest_pattern( acc, ctx, it, rest_pat) ,
169+ // FIXME
170+ // ast::TuplePat(it) => (),
171+ // FIXME
172+ // ast::SlicePat(it) => (),
173+ _ => return None ,
174+ }
175+ }
176+ }
177+
165178#[ cfg( test) ]
166179mod tests {
167180 use super :: * ;
0 commit comments