2
2
3
3
use algo:: find_covering_element;
4
4
use hir:: Semantics ;
5
- use ra_db:: { FileId , FileRange } ;
5
+ use ra_db:: { FileId , FileRange , FilePosition } ;
6
6
use ra_fmt:: { leading_indent, reindent} ;
7
7
use ra_ide_db:: {
8
8
source_change:: { SourceChange , SourceFileEdit } ,
@@ -19,6 +19,7 @@ use crate::{
19
19
assist_config:: { AssistConfig , SnippetCap } ,
20
20
Assist , AssistId , GroupLabel , ResolvedAssist ,
21
21
} ;
22
+ use rustc_hash:: FxHashMap ;
22
23
23
24
/// `AssistContext` allows to apply an assist or check if it could be applied.
24
25
///
@@ -138,6 +139,16 @@ impl Assists {
138
139
let label = Assist :: new ( id, label. into ( ) , None , target) ;
139
140
self . add_impl ( label, f)
140
141
}
142
+ pub ( crate ) fn add_in_multiple_files (
143
+ & mut self ,
144
+ id : AssistId ,
145
+ label : impl Into < String > ,
146
+ target : TextRange ,
147
+ f : impl FnOnce ( & mut AssistDirector ) ,
148
+ ) -> Option < ( ) > {
149
+ let label = Assist :: new ( id, label. into ( ) , None , target) ;
150
+ self . add_impl_multiple_files ( label, f)
151
+ }
141
152
pub ( crate ) fn add_group (
142
153
& mut self ,
143
154
group : & GroupLabel ,
@@ -162,6 +173,27 @@ impl Assists {
162
173
Some ( ( ) )
163
174
}
164
175
176
+ fn add_impl_multiple_files ( & mut self , label : Assist , f : impl FnOnce ( & mut AssistDirector ) ) -> Option < ( ) > {
177
+ let change_label = label. label . clone ( ) ;
178
+ if !self . resolve {
179
+ return None
180
+ }
181
+ let mut director = AssistDirector :: new ( change_label. clone ( ) ) ;
182
+ f ( & mut director) ;
183
+ let changes = director. finish ( ) ;
184
+ let file_edits: Vec < SourceFileEdit > = changes. into_iter ( )
185
+ . map ( |mut change| change. source_file_edits . pop ( ) . unwrap ( ) ) . collect ( ) ;
186
+
187
+ let source_change = SourceChange {
188
+ source_file_edits : file_edits,
189
+ file_system_edits : vec ! [ ] ,
190
+ is_snippet : false ,
191
+ } ;
192
+
193
+ self . buf . push ( ( label, Some ( source_change) ) ) ;
194
+ Some ( ( ) )
195
+ }
196
+
165
197
fn finish ( mut self ) -> Vec < ( Assist , Option < SourceChange > ) > {
166
198
self . buf . sort_by_key ( |( label, _edit) | label. target . len ( ) ) ;
167
199
self . buf
@@ -255,3 +287,31 @@ impl AssistBuilder {
255
287
res
256
288
}
257
289
}
290
+
291
+ pub ( crate ) struct AssistDirector {
292
+ source_changes : Vec < SourceChange > ,
293
+ builders : FxHashMap < FileId , AssistBuilder > ,
294
+ change_label : String
295
+ }
296
+
297
+ impl AssistDirector {
298
+ fn new ( change_label : String ) -> AssistDirector {
299
+ AssistDirector {
300
+ source_changes : vec ! [ ] ,
301
+ builders : FxHashMap :: default ( ) ,
302
+ change_label
303
+ }
304
+ }
305
+
306
+ pub ( crate ) fn perform ( & mut self , file_id : FileId , f : impl FnOnce ( & mut AssistBuilder ) ) {
307
+ let mut builder = self . builders . entry ( file_id) . or_insert ( AssistBuilder :: new ( file_id) ) ;
308
+ f ( & mut builder) ;
309
+ }
310
+
311
+ fn finish ( mut self ) -> Vec < SourceChange > {
312
+ for ( file_id, builder) in self . builders . into_iter ( ) . collect :: < Vec < ( FileId , AssistBuilder ) > > ( ) {
313
+ self . source_changes . push ( builder. finish ( ) ) ;
314
+ }
315
+ self . source_changes
316
+ }
317
+ }
0 commit comments