@@ -9,10 +9,11 @@ use ide_db::{
9
9
search:: FileReference ,
10
10
} ;
11
11
use itertools:: Itertools ;
12
+ use syntax:: ast:: syntax_factory:: SyntaxFactory ;
13
+ use syntax:: syntax_editor:: SyntaxEditor ;
12
14
use syntax:: {
13
15
AstNode , NodeOrToken , SyntaxNode ,
14
- ast:: { self , HasGenericParams , HasName , make} ,
15
- ted,
16
+ ast:: { self , HasGenericParams , HasName } ,
16
17
} ;
17
18
18
19
use crate :: {
@@ -68,37 +69,41 @@ pub(crate) fn inline_type_alias_uses(acc: &mut Assists, ctx: &AssistContext<'_>)
68
69
let mut definition_deleted = false ;
69
70
70
71
let mut inline_refs_for_file = |file_id, refs : Vec < FileReference > | {
71
- builder. edit_file ( file_id) ;
72
+ let source = ctx. sema . parse ( file_id) ;
73
+ let mut editor = builder. make_editor ( source. syntax ( ) ) ;
72
74
73
75
let ( path_types, path_type_uses) =
74
76
split_refs_and_uses ( builder, refs, |path_type| {
75
77
path_type. syntax ( ) . ancestors ( ) . nth ( 3 ) . and_then ( ast:: PathType :: cast)
76
78
} ) ;
77
-
78
79
path_type_uses
79
80
. iter ( )
80
81
. flat_map ( ast_to_remove_for_path_in_use_stmt)
81
- . for_each ( |x| builder. delete ( x. syntax ( ) . text_range ( ) ) ) ;
82
+ . for_each ( |x| editor. delete ( x. syntax ( ) ) ) ;
83
+
82
84
for ( target, replacement) in path_types. into_iter ( ) . filter_map ( |path_type| {
83
- let replacement = inline ( & ast_alias, & path_type) ?. to_text ( & concrete_type) ;
84
- let target = path_type. syntax ( ) . text_range ( ) ;
85
+ let replacement =
86
+ inline ( & ast_alias, & path_type) ?. replace_generic ( & concrete_type) ;
87
+ let target = path_type. syntax ( ) . clone ( ) ;
85
88
Some ( ( target, replacement) )
86
89
} ) {
87
- builder . replace ( target, replacement) ;
90
+ editor . replace ( target, replacement) ;
88
91
}
89
92
90
- if file_id == ctx. vfs_file_id ( ) {
91
- builder . delete ( ast_alias. syntax ( ) . text_range ( ) ) ;
93
+ if file_id. file_id ( ctx . db ( ) ) == ctx. vfs_file_id ( ) {
94
+ editor . delete ( ast_alias. syntax ( ) ) ;
92
95
definition_deleted = true ;
93
96
}
97
+ builder. add_file_edits ( file_id. file_id ( ctx. db ( ) ) , editor) ;
94
98
} ;
95
99
96
100
for ( file_id, refs) in usages. into_iter ( ) {
97
- inline_refs_for_file ( file_id. file_id ( ctx . db ( ) ) , refs) ;
101
+ inline_refs_for_file ( file_id, refs) ;
98
102
}
99
103
if !definition_deleted {
100
- builder. edit_file ( ctx. vfs_file_id ( ) ) ;
101
- builder. delete ( ast_alias. syntax ( ) . text_range ( ) ) ;
104
+ let mut editor = builder. make_editor ( ast_alias. syntax ( ) ) ;
105
+ editor. delete ( ast_alias. syntax ( ) ) ;
106
+ builder. add_file_edits ( ctx. vfs_file_id ( ) , editor)
102
107
}
103
108
} ,
104
109
)
@@ -146,23 +151,26 @@ pub(crate) fn inline_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
146
151
}
147
152
}
148
153
149
- let target = alias_instance. syntax ( ) . text_range ( ) ;
150
-
151
154
acc. add (
152
155
AssistId :: refactor_inline ( "inline_type_alias" ) ,
153
156
"Inline type alias" ,
154
- target,
155
- |builder| builder. replace ( target, replacement. to_text ( & concrete_type) ) ,
157
+ alias_instance. syntax ( ) . text_range ( ) ,
158
+ |builder| {
159
+ let mut editor = builder. make_editor ( alias_instance. syntax ( ) ) ;
160
+ let replace = replacement. replace_generic ( & concrete_type) ;
161
+ editor. replace ( alias_instance. syntax ( ) , replace) ;
162
+ builder. add_file_edits ( ctx. vfs_file_id ( ) , editor) ;
163
+ } ,
156
164
)
157
165
}
158
166
159
167
impl Replacement {
160
- fn to_text ( & self , concrete_type : & ast:: Type ) -> String {
168
+ fn replace_generic ( & self , concrete_type : & ast:: Type ) -> SyntaxNode {
161
169
match self {
162
170
Replacement :: Generic { lifetime_map, const_and_type_map } => {
163
171
create_replacement ( lifetime_map, const_and_type_map, concrete_type)
164
172
}
165
- Replacement :: Plain => concrete_type. to_string ( ) ,
173
+ Replacement :: Plain => concrete_type. syntax ( ) . clone_subtree ( ) . clone_for_update ( ) ,
166
174
}
167
175
}
168
176
}
@@ -199,8 +207,8 @@ impl LifetimeMap {
199
207
alias_generics : & ast:: GenericParamList ,
200
208
) -> Option < Self > {
201
209
let mut inner = FxHashMap :: default ( ) ;
202
-
203
- let wildcard_lifetime = make:: lifetime ( "'_" ) ;
210
+ let make = SyntaxFactory :: without_mappings ( ) ;
211
+ let wildcard_lifetime = make. lifetime ( "'_" ) ;
204
212
let lifetimes = alias_generics
205
213
. lifetime_params ( )
206
214
. filter_map ( |lp| lp. lifetime ( ) )
@@ -299,15 +307,14 @@ fn create_replacement(
299
307
lifetime_map : & LifetimeMap ,
300
308
const_and_type_map : & ConstAndTypeMap ,
301
309
concrete_type : & ast:: Type ,
302
- ) -> String {
303
- let updated_concrete_type = concrete_type. clone_for_update ( ) ;
304
- let mut replacements = Vec :: new ( ) ;
305
- let mut removals = Vec :: new ( ) ;
310
+ ) -> SyntaxNode {
311
+ let updated_concrete_type = concrete_type. syntax ( ) . clone_subtree ( ) ;
312
+ let mut editor = SyntaxEditor :: new ( updated_concrete_type. clone ( ) ) ;
306
313
307
- for syntax in updated_concrete_type. syntax ( ) . descendants ( ) {
308
- let syntax_string = syntax. to_string ( ) ;
309
- let syntax_str = syntax_string. as_str ( ) ;
314
+ let mut replacements: Vec < ( SyntaxNode , SyntaxNode ) > = Vec :: new ( ) ;
315
+ let mut removals: Vec < NodeOrToken < SyntaxNode , _ > > = Vec :: new ( ) ;
310
316
317
+ for syntax in updated_concrete_type. descendants ( ) {
311
318
if let Some ( old_lifetime) = ast:: Lifetime :: cast ( syntax. clone ( ) ) {
312
319
if let Some ( new_lifetime) = lifetime_map. 0 . get ( & old_lifetime. to_string ( ) ) {
313
320
if new_lifetime. text ( ) == "'_" {
@@ -322,27 +329,30 @@ fn create_replacement(
322
329
323
330
replacements. push ( ( syntax. clone ( ) , new_lifetime. syntax ( ) . clone_for_update ( ) ) ) ;
324
331
}
325
- } else if let Some ( replacement_syntax) = const_and_type_map. 0 . get ( syntax_str) {
332
+ } else if let Some ( name_ref) = ast:: NameRef :: cast ( syntax. clone ( ) ) {
333
+ let Some ( replacement_syntax) = const_and_type_map. 0 . get ( & name_ref. to_string ( ) ) else {
334
+ continue ;
335
+ } ;
326
336
let new_string = replacement_syntax. to_string ( ) ;
327
337
let new = if new_string == "_" {
328
- make:: wildcard_pat ( ) . syntax ( ) . clone_for_update ( )
338
+ let make = SyntaxFactory :: without_mappings ( ) ;
339
+ make. wildcard_pat ( ) . syntax ( ) . clone ( )
329
340
} else {
330
- replacement_syntax. clone_for_update ( )
341
+ replacement_syntax. clone ( )
331
342
} ;
332
343
333
344
replacements. push ( ( syntax. clone ( ) , new) ) ;
334
345
}
335
346
}
336
347
337
348
for ( old, new) in replacements {
338
- ted :: replace ( old, new) ;
349
+ editor . replace ( old, new) ;
339
350
}
340
351
341
352
for syntax in removals {
342
- ted :: remove ( syntax) ;
353
+ editor . delete ( syntax) ;
343
354
}
344
-
345
- updated_concrete_type. to_string ( )
355
+ editor. finish ( ) . new_root ( ) . clone ( )
346
356
}
347
357
348
358
fn get_type_alias ( ctx : & AssistContext < ' _ > , path : & ast:: PathType ) -> Option < ast:: TypeAlias > {
@@ -377,12 +387,15 @@ impl ConstOrTypeGeneric {
377
387
}
378
388
379
389
fn replacement_value ( & self ) -> Option < SyntaxNode > {
380
- Some ( match self {
381
- ConstOrTypeGeneric :: ConstArg ( ca) => ca. expr ( ) ?. syntax ( ) . clone ( ) ,
382
- ConstOrTypeGeneric :: TypeArg ( ta) => ta. syntax ( ) . clone ( ) ,
383
- ConstOrTypeGeneric :: ConstParam ( cp) => cp. default_val ( ) ?. syntax ( ) . clone ( ) ,
384
- ConstOrTypeGeneric :: TypeParam ( tp) => tp. default_type ( ) ?. syntax ( ) . clone ( ) ,
385
- } )
390
+ Some (
391
+ match self {
392
+ ConstOrTypeGeneric :: ConstArg ( ca) => ca. expr ( ) ?. syntax ( ) . clone ( ) ,
393
+ ConstOrTypeGeneric :: TypeArg ( ta) => ta. syntax ( ) . clone ( ) ,
394
+ ConstOrTypeGeneric :: ConstParam ( cp) => cp. default_val ( ) ?. syntax ( ) . clone ( ) ,
395
+ ConstOrTypeGeneric :: TypeParam ( tp) => tp. default_type ( ) ?. syntax ( ) . clone ( ) ,
396
+ }
397
+ . clone_for_update ( ) ,
398
+ )
386
399
}
387
400
}
388
401
0 commit comments