@@ -30,7 +30,7 @@ use syntax::{
3030 ast:: { self , NameOwner } ,
3131 lex_single_syntax_kind, AstNode , SyntaxKind , TextRange , T ,
3232} ;
33- use text_edit:: TextEdit ;
33+ use text_edit:: { TextEdit , TextEditBuilder } ;
3434
3535use crate :: {
3636 defs:: Definition ,
@@ -303,28 +303,29 @@ pub fn source_edit_from_references(
303303) -> TextEdit {
304304 let mut edit = TextEdit :: builder ( ) ;
305305 for reference in references {
306- let ( range , replacement ) = match & reference. name {
306+ let has_emitted_edit = match & reference. name {
307307 // if the ranges differ then the node is inside a macro call, we can't really attempt
308308 // to make special rewrites like shorthand syntax and such, so just rename the node in
309309 // the macro input
310310 ast:: NameLike :: NameRef ( name_ref)
311311 if name_ref. syntax ( ) . text_range ( ) == reference. range =>
312312 {
313- source_edit_from_name_ref ( name_ref, new_name, def)
313+ source_edit_from_name_ref ( & mut edit , name_ref, new_name, def)
314314 }
315315 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)
317317 }
318- _ => None ,
318+ _ => false ,
319+ } ;
320+ if !has_emitted_edit {
321+ edit. replace ( reference. range , new_name. to_string ( ) ) ;
319322 }
320- . unwrap_or_else ( || ( reference. range , new_name. to_string ( ) ) ) ;
321- edit. replace ( range, replacement) ;
322323 }
323324
324325 edit. finish ( )
325326}
326327
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 {
328329 if let Some ( _) = ast:: RecordPatField :: for_field_name ( name) {
329330 if let Some ( ident_pat) = name. syntax ( ) . parent ( ) . and_then ( ast:: IdentPat :: cast) {
330331 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,
333334
334335 // FIXME: instead of splitting the shorthand, recursively trigger a rename of the
335336 // 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 ;
340339 }
341340 }
342341
343- None
342+ false
344343}
345344
346345fn source_edit_from_name_ref (
346+ edit : & mut TextEditBuilder ,
347347 name_ref : & ast:: NameRef ,
348348 new_name : & str ,
349349 def : Definition ,
350- ) -> Option < ( TextRange , String ) > {
350+ ) -> bool {
351351 if let Some ( record_field) = ast:: RecordExprField :: for_name_ref ( name_ref) {
352352 let rcf_name_ref = record_field. name_ref ( ) ;
353353 let rcf_expr = record_field. expr ( ) ;
@@ -358,47 +358,48 @@ fn source_edit_from_name_ref(
358358 if init. text ( ) == new_name {
359359 cov_mark:: hit!( test_rename_field_put_init_shorthand) ;
360360 // Foo { field: local } -> Foo { local }
361- // ^^^^^^^^ delete this
362- // FIXME: Actually delete this instead of replacing the entire thing
361+ // ^^^^^^^ delete this
363362
364363 // same names, we can use a shorthand here instead.
365364 // we do not want to erase attributes hence this range start
366365 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 ;
369369 }
370370 } else if init == name_ref {
371371 if field_name. text ( ) == new_name {
372372 cov_mark:: hit!( test_rename_local_put_init_shorthand) ;
373373 // Foo { field: local } -> Foo { field }
374374 // ^^^^^^^ delete this
375- // FIXME: Actually delete this instead of replacing the entire thing
376375
377376 // same names, we can use a shorthand here instead.
378377 // 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 ;
382382 }
383383 }
384- None
385384 }
386385 // init shorthand
387386 ( None , Some ( _) ) if matches ! ( def, Definition :: Field ( _) ) => {
388387 cov_mark:: hit!( test_rename_field_in_field_shorthand) ;
389388 // Foo { field } -> Foo { new_name: field }
390389 // ^ 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 ;
393393 }
394394 ( None , Some ( _) ) if matches ! ( def, Definition :: Local ( _) ) => {
395395 cov_mark:: hit!( test_rename_local_in_field_shorthand) ;
396396 // Foo { field } -> Foo { field: new_name }
397397 // ^ 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 ;
400401 }
401- _ => None ,
402+ _ => ( ) ,
402403 }
403404 } else if let Some ( record_field) = ast:: RecordPatField :: for_field_name_ref ( name_ref) {
404405 let rcf_name_ref = record_field. name_ref ( ) ;
@@ -409,27 +410,27 @@ fn source_edit_from_name_ref(
409410 if field_name == * name_ref && pat. at_token ( ) . is_none ( ) =>
410411 {
411412 // 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+ }
426428 }
427429 }
428- _ => None ,
430+ _ => ( ) ,
429431 }
430- } else {
431- None
432432 }
433+ false
433434}
434435
435436fn source_edit_from_def (
0 commit comments