@@ -2,28 +2,12 @@ use hir::{PathResolution, StructKind};
2
2
use ide_db:: syntax_helpers:: suggest_name:: NameGenerator ;
3
3
use syntax:: {
4
4
AstNode , ToSmolStr ,
5
- ast:: { self , make } ,
5
+ ast:: { self , syntax_factory :: SyntaxFactory } ,
6
6
match_ast,
7
7
} ;
8
8
9
9
use crate :: { AssistContext , AssistId , Assists } ;
10
10
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
-
27
11
// Assist: expand_record_rest_pattern
28
12
//
29
13
// Fills fields by replacing rest pattern in record patterns.
@@ -50,7 +34,6 @@ fn expand_record_rest_pattern(
50
34
rest_pat : ast:: RestPat ,
51
35
) -> Option < ( ) > {
52
36
let missing_fields = ctx. sema . record_pattern_missing_fields ( & record_pat) ;
53
-
54
37
if missing_fields. is_empty ( ) {
55
38
cov_mark:: hit!( no_missing_fields) ;
56
39
return None ;
@@ -62,24 +45,30 @@ fn expand_record_rest_pattern(
62
45
return None ;
63
46
}
64
47
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 ( ) ) ;
76
49
acc. add (
77
50
AssistId :: refactor_rewrite ( "expand_record_rest_pattern" ) ,
78
51
"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
+ } ,
81
69
)
82
70
}
71
+
83
72
// Assist: expand_tuple_struct_rest_pattern
84
73
//
85
74
// Fills fields by replacing rest pattern in tuple struct patterns.
@@ -134,34 +123,58 @@ fn expand_tuple_struct_rest_pattern(
134
123
return None ;
135
124
}
136
125
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 ( ) ;
157
126
acc. add (
158
127
AssistId :: refactor_rewrite ( "expand_tuple_struct_rest_pattern" ) ,
159
128
"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
+ } ,
162
159
)
163
160
}
164
161
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
+
165
178
#[ cfg( test) ]
166
179
mod tests {
167
180
use super :: * ;
0 commit comments