@@ -183,25 +183,41 @@ fn source_edit_from_references(
183
183
) -> ( FileId , TextEdit ) {
184
184
let mut edit = TextEdit :: builder ( ) ;
185
185
for reference in references {
186
- match reference. name . as_name_ref ( ) {
186
+ let ( range , replacement ) = match & reference. name {
187
187
// if the ranges differ then the node is inside a macro call, we can't really attempt
188
188
// to make special rewrites like shorthand syntax and such, so just rename the node in
189
189
// the macro input
190
- Some ( name_ref) if name_ref. syntax ( ) . text_range ( ) == reference. range => {
191
- let ( range, replacement) = source_edit_from_name_ref ( name_ref, new_name, def) ;
192
- edit. replace ( range, replacement) ;
190
+ NameLike :: NameRef ( name_ref) if name_ref. syntax ( ) . text_range ( ) == reference. range => {
191
+ source_edit_from_name_ref ( name_ref, new_name, def)
193
192
}
194
- _ => edit. replace ( reference. range , new_name. to_owned ( ) ) ,
195
- } ;
193
+ NameLike :: Name ( name) if name. syntax ( ) . text_range ( ) == reference. range => {
194
+ source_edit_from_name ( name, new_name)
195
+ }
196
+ _ => None ,
197
+ }
198
+ . unwrap_or_else ( || ( reference. range , new_name. to_string ( ) ) ) ;
199
+ edit. replace ( range, replacement) ;
196
200
}
197
201
( file_id, edit. finish ( ) )
198
202
}
199
203
204
+ fn source_edit_from_name ( name : & ast:: Name , new_name : & str ) -> Option < ( TextRange , String ) > {
205
+ if let Some ( _) = ast:: RecordPatField :: for_field_name ( name) {
206
+ if let Some ( ident_pat) = name. syntax ( ) . parent ( ) . and_then ( ast:: IdentPat :: cast) {
207
+ return Some ( (
208
+ TextRange :: empty ( ident_pat. syntax ( ) . text_range ( ) . start ( ) ) ,
209
+ format ! ( "{}: " , new_name) ,
210
+ ) ) ;
211
+ }
212
+ }
213
+ None
214
+ }
215
+
200
216
fn source_edit_from_name_ref (
201
217
name_ref : & ast:: NameRef ,
202
218
new_name : & str ,
203
219
def : Definition ,
204
- ) -> ( TextRange , String ) {
220
+ ) -> Option < ( TextRange , String ) > {
205
221
if let Some ( record_field) = ast:: RecordExprField :: for_name_ref ( name_ref) {
206
222
let rcf_name_ref = record_field. name_ref ( ) ;
207
223
let rcf_expr = record_field. expr ( ) ;
@@ -215,7 +231,7 @@ fn source_edit_from_name_ref(
215
231
// we do not want to erase attributes hence this range start
216
232
let s = field_name. syntax ( ) . text_range ( ) . start ( ) ;
217
233
let e = record_field. syntax ( ) . text_range ( ) . end ( ) ;
218
- return ( TextRange :: new ( s, e) , new_name. to_owned ( ) ) ;
234
+ return Some ( ( TextRange :: new ( s, e) , new_name. to_owned ( ) ) ) ;
219
235
}
220
236
} else if init == * name_ref {
221
237
if field_name. text ( ) == new_name {
@@ -224,32 +240,27 @@ fn source_edit_from_name_ref(
224
240
// we do not want to erase attributes hence this range start
225
241
let s = field_name. syntax ( ) . text_range ( ) . start ( ) ;
226
242
let e = record_field. syntax ( ) . text_range ( ) . end ( ) ;
227
- return ( TextRange :: new ( s, e) , new_name. to_owned ( ) ) ;
243
+ return Some ( ( TextRange :: new ( s, e) , new_name. to_owned ( ) ) ) ;
228
244
}
229
245
}
246
+ None
230
247
}
231
248
// init shorthand
232
- ( None , Some ( _) ) => {
233
- // FIXME: instead of splitting the shorthand, recursively trigger a rename of the
234
- // other name https://github.com/rust-analyzer/rust-analyzer/issues/6547
235
- match def {
236
- Definition :: Field ( _) => {
237
- mark:: hit!( test_rename_field_in_field_shorthand) ;
238
- let s = name_ref. syntax ( ) . text_range ( ) . start ( ) ;
239
- return ( TextRange :: empty ( s) , format ! ( "{}: " , new_name) ) ;
240
- }
241
- Definition :: Local ( _) => {
242
- mark:: hit!( test_rename_local_in_field_shorthand) ;
243
- let s = name_ref. syntax ( ) . text_range ( ) . end ( ) ;
244
- return ( TextRange :: empty ( s) , format ! ( ": {}" , new_name) ) ;
245
- }
246
- _ => { }
247
- }
249
+ // FIXME: instead of splitting the shorthand, recursively trigger a rename of the
250
+ // other name https://github.com/rust-analyzer/rust-analyzer/issues/6547
251
+ ( None , Some ( _) ) if matches ! ( def, Definition :: Field ( _) ) => {
252
+ mark:: hit!( test_rename_field_in_field_shorthand) ;
253
+ let s = name_ref. syntax ( ) . text_range ( ) . start ( ) ;
254
+ Some ( ( TextRange :: empty ( s) , format ! ( "{}: " , new_name) ) )
255
+ }
256
+ ( None , Some ( _) ) if matches ! ( def, Definition :: Local ( _) ) => {
257
+ mark:: hit!( test_rename_local_in_field_shorthand) ;
258
+ let s = name_ref. syntax ( ) . text_range ( ) . end ( ) ;
259
+ Some ( ( TextRange :: empty ( s) , format ! ( ": {}" , new_name) ) )
248
260
}
249
- _ => { }
261
+ _ => None ,
250
262
}
251
- }
252
- if let Some ( record_field) = ast:: RecordPatField :: for_field_name_ref ( name_ref) {
263
+ } else if let Some ( record_field) = ast:: RecordPatField :: for_field_name_ref ( name_ref) {
253
264
let rcf_name_ref = record_field. name_ref ( ) ;
254
265
let rcf_pat = record_field. pat ( ) ;
255
266
match ( rcf_name_ref, rcf_pat) {
@@ -262,13 +273,16 @@ fn source_edit_from_name_ref(
262
273
// we do not want to erase attributes hence this range start
263
274
let s = field_name. syntax ( ) . text_range ( ) . start ( ) ;
264
275
let e = record_field. syntax ( ) . text_range ( ) . end ( ) ;
265
- return ( TextRange :: new ( s, e) , new_name. to_owned ( ) ) ;
276
+ Some ( ( TextRange :: new ( s, e) , pat. to_string ( ) ) )
277
+ } else {
278
+ None
266
279
}
267
280
}
268
- _ => { }
281
+ _ => None ,
269
282
}
283
+ } else {
284
+ None
270
285
}
271
- ( name_ref. syntax ( ) . text_range ( ) , new_name. to_owned ( ) )
272
286
}
273
287
274
288
fn rename_mod (
@@ -1491,24 +1505,24 @@ fn foo(i: i32) -> Foo {
1491
1505
}
1492
1506
1493
1507
#[ test]
1494
- fn test_struct_field_destructure_into_shorthand ( ) {
1508
+ fn test_struct_field_pat_into_shorthand ( ) {
1495
1509
mark:: check!( test_rename_field_put_init_shorthand_pat) ;
1496
1510
check (
1497
1511
"baz" ,
1498
1512
r#"
1499
1513
struct Foo { i$0: i32 }
1500
1514
1501
1515
fn foo(foo: Foo) {
1502
- let Foo { i: baz } = foo;
1503
- let _ = baz ;
1516
+ let Foo { i: ref baz @ qux } = foo;
1517
+ let _ = qux ;
1504
1518
}
1505
1519
"# ,
1506
1520
r#"
1507
1521
struct Foo { baz: i32 }
1508
1522
1509
1523
fn foo(foo: Foo) {
1510
- let Foo { baz } = foo;
1511
- let _ = baz ;
1524
+ let Foo { ref baz @ qux } = foo;
1525
+ let _ = qux ;
1512
1526
}
1513
1527
"# ,
1514
1528
) ;
@@ -1581,6 +1595,27 @@ fn foo(Foo { i: bar }: foo) -> i32 {
1581
1595
)
1582
1596
}
1583
1597
1598
+ #[ test]
1599
+ fn test_struct_field_complex_ident_pat ( ) {
1600
+ check (
1601
+ "baz" ,
1602
+ r#"
1603
+ struct Foo { i$0: i32 }
1604
+
1605
+ fn foo(foo: Foo) {
1606
+ let Foo { ref i } = foo;
1607
+ }
1608
+ "# ,
1609
+ r#"
1610
+ struct Foo { baz: i32 }
1611
+
1612
+ fn foo(foo: Foo) {
1613
+ let Foo { baz: ref i } = foo;
1614
+ }
1615
+ "# ,
1616
+ ) ;
1617
+ }
1618
+
1584
1619
#[ test]
1585
1620
fn test_rename_lifetimes ( ) {
1586
1621
mark:: check!( rename_lifetime) ;
0 commit comments