@@ -30,7 +30,7 @@ use syntax::{
30
30
ast:: { self , NameOwner } ,
31
31
lex_single_syntax_kind, AstNode , SyntaxKind , TextRange , T ,
32
32
} ;
33
- use text_edit:: TextEdit ;
33
+ use text_edit:: { TextEdit , TextEditBuilder } ;
34
34
35
35
use crate :: {
36
36
defs:: Definition ,
@@ -303,28 +303,29 @@ pub fn source_edit_from_references(
303
303
) -> TextEdit {
304
304
let mut edit = TextEdit :: builder ( ) ;
305
305
for reference in references {
306
- let ( range , replacement ) = match & reference. name {
306
+ let has_emitted_edit = match & reference. name {
307
307
// if the ranges differ then the node is inside a macro call, we can't really attempt
308
308
// to make special rewrites like shorthand syntax and such, so just rename the node in
309
309
// the macro input
310
310
ast:: NameLike :: NameRef ( name_ref)
311
311
if name_ref. syntax ( ) . text_range ( ) == reference. range =>
312
312
{
313
- source_edit_from_name_ref ( name_ref, new_name, def)
313
+ source_edit_from_name_ref ( & mut edit , name_ref, new_name, def)
314
314
}
315
315
ast:: NameLike :: Name ( name) if name. syntax ( ) . text_range ( ) == reference. range => {
316
- source_edit_from_name ( name, new_name)
316
+ source_edit_from_name ( & mut edit , name, new_name)
317
317
}
318
- _ => None ,
318
+ _ => false ,
319
+ } ;
320
+ if !has_emitted_edit {
321
+ edit. replace ( reference. range , new_name. to_string ( ) ) ;
319
322
}
320
- . unwrap_or_else ( || ( reference. range , new_name. to_string ( ) ) ) ;
321
- edit. replace ( range, replacement) ;
322
323
}
323
324
324
325
edit. finish ( )
325
326
}
326
327
327
- fn source_edit_from_name ( name : & ast:: Name , new_name : & str ) -> Option < ( TextRange , String ) > {
328
+ fn source_edit_from_name ( edit : & mut TextEditBuilder , name : & ast:: Name , new_name : & str ) -> bool {
328
329
if let Some ( _) = ast:: RecordPatField :: for_field_name ( name) {
329
330
if let Some ( ident_pat) = name. syntax ( ) . parent ( ) . and_then ( ast:: IdentPat :: cast) {
330
331
cov_mark:: hit!( rename_record_pat_field_name_split) ;
@@ -333,21 +334,20 @@ fn source_edit_from_name(name: &ast::Name, new_name: &str) -> Option<(TextRange,
333
334
334
335
// FIXME: instead of splitting the shorthand, recursively trigger a rename of the
335
336
// other name https://github.com/rust-analyzer/rust-analyzer/issues/6547
336
- return Some ( (
337
- TextRange :: empty ( ident_pat. syntax ( ) . text_range ( ) . start ( ) ) ,
338
- format ! ( "{}: " , new_name) ,
339
- ) ) ;
337
+ edit. insert ( ident_pat. syntax ( ) . text_range ( ) . start ( ) , format ! ( "{}: " , new_name) ) ;
338
+ return true ;
340
339
}
341
340
}
342
341
343
- None
342
+ false
344
343
}
345
344
346
345
fn source_edit_from_name_ref (
346
+ edit : & mut TextEditBuilder ,
347
347
name_ref : & ast:: NameRef ,
348
348
new_name : & str ,
349
349
def : Definition ,
350
- ) -> Option < ( TextRange , String ) > {
350
+ ) -> bool {
351
351
if let Some ( record_field) = ast:: RecordExprField :: for_name_ref ( name_ref) {
352
352
let rcf_name_ref = record_field. name_ref ( ) ;
353
353
let rcf_expr = record_field. expr ( ) ;
@@ -358,47 +358,48 @@ fn source_edit_from_name_ref(
358
358
if init. text ( ) == new_name {
359
359
cov_mark:: hit!( test_rename_field_put_init_shorthand) ;
360
360
// Foo { field: local } -> Foo { local }
361
- // ^^^^^^^^ delete this
362
- // FIXME: Actually delete this instead of replacing the entire thing
361
+ // ^^^^^^^ delete this
363
362
364
363
// same names, we can use a shorthand here instead.
365
364
// we do not want to erase attributes hence this range start
366
365
let s = field_name. syntax ( ) . text_range ( ) . start ( ) ;
367
- let e = record_field. syntax ( ) . text_range ( ) . end ( ) ;
368
- return Some ( ( TextRange :: new ( s, e) , new_name. to_owned ( ) ) ) ;
366
+ let e = init. syntax ( ) . text_range ( ) . start ( ) ;
367
+ edit. delete ( TextRange :: new ( s, e) ) ;
368
+ return true ;
369
369
}
370
370
} else if init == name_ref {
371
371
if field_name. text ( ) == new_name {
372
372
cov_mark:: hit!( test_rename_local_put_init_shorthand) ;
373
373
// Foo { field: local } -> Foo { field }
374
374
// ^^^^^^^ delete this
375
- // FIXME: Actually delete this instead of replacing the entire thing
376
375
377
376
// same names, we can use a shorthand here instead.
378
377
// we do not want to erase attributes hence this range start
379
- let s = field_name. syntax ( ) . text_range ( ) . start ( ) ;
380
- let e = record_field. syntax ( ) . text_range ( ) . end ( ) ;
381
- return Some ( ( TextRange :: new ( s, e) , new_name. to_owned ( ) ) ) ;
378
+ let s = field_name. syntax ( ) . text_range ( ) . end ( ) ;
379
+ let e = init. syntax ( ) . text_range ( ) . end ( ) ;
380
+ edit. delete ( TextRange :: new ( s, e) ) ;
381
+ return true ;
382
382
}
383
383
}
384
- None
385
384
}
386
385
// init shorthand
387
386
( None , Some ( _) ) if matches ! ( def, Definition :: Field ( _) ) => {
388
387
cov_mark:: hit!( test_rename_field_in_field_shorthand) ;
389
388
// Foo { field } -> Foo { new_name: field }
390
389
// ^ insert `new_name: `
391
- let s = name_ref. syntax ( ) . text_range ( ) . start ( ) ;
392
- Some ( ( TextRange :: empty ( s) , format ! ( "{}: " , new_name) ) )
390
+ let offset = name_ref. syntax ( ) . text_range ( ) . start ( ) ;
391
+ edit. insert ( offset, format ! ( "{}: " , new_name) ) ;
392
+ return true ;
393
393
}
394
394
( None , Some ( _) ) if matches ! ( def, Definition :: Local ( _) ) => {
395
395
cov_mark:: hit!( test_rename_local_in_field_shorthand) ;
396
396
// Foo { field } -> Foo { field: new_name }
397
397
// ^ insert `: new_name`
398
- let s = name_ref. syntax ( ) . text_range ( ) . end ( ) ;
399
- Some ( ( TextRange :: empty ( s) , format ! ( ": {}" , new_name) ) )
398
+ let offset = name_ref. syntax ( ) . text_range ( ) . end ( ) ;
399
+ edit. insert ( offset, format ! ( ": {}" , new_name) ) ;
400
+ return true ;
400
401
}
401
- _ => None ,
402
+ _ => ( ) ,
402
403
}
403
404
} else if let Some ( record_field) = ast:: RecordPatField :: for_field_name_ref ( name_ref) {
404
405
let rcf_name_ref = record_field. name_ref ( ) ;
@@ -409,27 +410,27 @@ fn source_edit_from_name_ref(
409
410
if field_name == * name_ref && pat. at_token ( ) . is_none ( ) =>
410
411
{
411
412
// field name is being renamed
412
- if pat. name ( ) . map_or ( false , |it| it. text ( ) == new_name) {
413
- cov_mark:: hit!( test_rename_field_put_init_shorthand_pat) ;
414
- // Foo { field: ref mut local } -> Foo { ref mut field }
415
- // ^^^^^^^ delete this
416
- // ^^^^^ replace this with `field`
417
- // FIXME: do this the way its written here
418
-
419
- // same names, we can use a shorthand here instead/
420
- // we do not want to erase attributes hence this range start
421
- let s = field_name. syntax ( ) . text_range ( ) . start ( ) ;
422
- let e = record_field. syntax ( ) . text_range ( ) . end ( ) ;
423
- Some ( ( TextRange :: new ( s, e) , pat. to_string ( ) ) )
424
- } else {
425
- None
413
+ if let Some ( name) = pat. name ( ) {
414
+ if name. text ( ) == new_name {
415
+ cov_mark:: hit!( test_rename_field_put_init_shorthand_pat) ;
416
+ // Foo { field: ref mut local } -> Foo { ref mut field }
417
+ // ^^^^^^^ delete this
418
+ // ^^^^^ replace this with `field`
419
+
420
+ // same names, we can use a shorthand here instead/
421
+ // we do not want to erase attributes hence this range start
422
+ let s = field_name. syntax ( ) . text_range ( ) . start ( ) ;
423
+ let e = pat. syntax ( ) . text_range ( ) . start ( ) ;
424
+ edit. delete ( TextRange :: new ( s, e) ) ;
425
+ edit. replace ( name. syntax ( ) . text_range ( ) , new_name. to_string ( ) ) ;
426
+ return true ;
427
+ }
426
428
}
427
429
}
428
- _ => None ,
430
+ _ => ( ) ,
429
431
}
430
- } else {
431
- None
432
432
}
433
+ false
433
434
}
434
435
435
436
fn source_edit_from_def (
0 commit comments