diff options
Diffstat (limited to 'crates/ra_ide')
-rw-r--r-- | crates/ra_ide/src/references/rename.rs | 208 |
1 files changed, 187 insertions, 21 deletions
diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs index 5b4bcf434..7d1190af9 100644 --- a/crates/ra_ide/src/references/rename.rs +++ b/crates/ra_ide/src/references/rename.rs | |||
@@ -9,7 +9,8 @@ use ra_syntax::{ | |||
9 | use ra_text_edit::TextEdit; | 9 | use ra_text_edit::TextEdit; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | FileId, FilePosition, FileSystemEdit, RangeInfo, SourceChange, SourceFileEdit, TextRange, | 12 | FilePosition, FileSystemEdit, RangeInfo, Reference, ReferenceKind, SourceChange, |
13 | SourceFileEdit, TextRange, | ||
13 | }; | 14 | }; |
14 | 15 | ||
15 | use super::find_all_refs; | 16 | use super::find_all_refs; |
@@ -46,12 +47,29 @@ fn find_name_and_module_at_offset( | |||
46 | Some((ast_name, ast_module)) | 47 | Some((ast_name, ast_module)) |
47 | } | 48 | } |
48 | 49 | ||
49 | fn source_edit_from_file_id_range( | 50 | fn source_edit_from_reference(reference: Reference, new_name: &str) -> SourceFileEdit { |
50 | file_id: FileId, | 51 | let mut replacement_text = String::new(); |
51 | range: TextRange, | 52 | let file_id = reference.file_range.file_id; |
52 | new_name: &str, | 53 | let range = match reference.kind { |
53 | ) -> SourceFileEdit { | 54 | ReferenceKind::StructFieldShorthandForField => { |
54 | SourceFileEdit { file_id, edit: TextEdit::replace(range, new_name.into()) } | 55 | replacement_text.push_str(new_name); |
56 | replacement_text.push_str(": "); | ||
57 | TextRange::from_to( | ||
58 | reference.file_range.range.start(), | ||
59 | reference.file_range.range.start(), | ||
60 | ) | ||
61 | } | ||
62 | ReferenceKind::StructFieldShorthandForLocal => { | ||
63 | replacement_text.push_str(": "); | ||
64 | replacement_text.push_str(new_name); | ||
65 | TextRange::from_to(reference.file_range.range.end(), reference.file_range.range.end()) | ||
66 | } | ||
67 | _ => { | ||
68 | replacement_text.push_str(new_name); | ||
69 | reference.file_range.range | ||
70 | } | ||
71 | }; | ||
72 | SourceFileEdit { file_id, edit: TextEdit::replace(range, replacement_text) } | ||
55 | } | 73 | } |
56 | 74 | ||
57 | fn rename_mod( | 75 | fn rename_mod( |
@@ -99,13 +117,10 @@ fn rename_mod( | |||
99 | source_file_edits.push(edit); | 117 | source_file_edits.push(edit); |
100 | 118 | ||
101 | if let Some(RangeInfo { range: _, info: refs }) = find_all_refs(sema.db, position, None) { | 119 | if let Some(RangeInfo { range: _, info: refs }) = find_all_refs(sema.db, position, None) { |
102 | let ref_edits = refs.references.into_iter().map(|reference| { | 120 | let ref_edits = refs |
103 | source_edit_from_file_id_range( | 121 | .references |
104 | reference.file_range.file_id, | 122 | .into_iter() |
105 | reference.file_range.range, | 123 | .map(|reference| source_edit_from_reference(reference, new_name)); |
106 | new_name, | ||
107 | ) | ||
108 | }); | ||
109 | source_file_edits.extend(ref_edits); | 124 | source_file_edits.extend(ref_edits); |
110 | } | 125 | } |
111 | 126 | ||
@@ -121,13 +136,7 @@ fn rename_reference( | |||
121 | 136 | ||
122 | let edit = refs | 137 | let edit = refs |
123 | .into_iter() | 138 | .into_iter() |
124 | .map(|reference| { | 139 | .map(|reference| source_edit_from_reference(reference, new_name)) |
125 | source_edit_from_file_id_range( | ||
126 | reference.file_range.file_id, | ||
127 | reference.file_range.range, | ||
128 | new_name, | ||
129 | ) | ||
130 | }) | ||
131 | .collect::<Vec<_>>(); | 140 | .collect::<Vec<_>>(); |
132 | 141 | ||
133 | if edit.is_empty() { | 142 | if edit.is_empty() { |
@@ -286,6 +295,163 @@ mod tests { | |||
286 | } | 295 | } |
287 | 296 | ||
288 | #[test] | 297 | #[test] |
298 | fn test_rename_struct_field() { | ||
299 | test_rename( | ||
300 | r#" | ||
301 | struct Foo { | ||
302 | i<|>: i32, | ||
303 | } | ||
304 | |||
305 | impl Foo { | ||
306 | fn new(i: i32) -> Self { | ||
307 | Self { i: i } | ||
308 | } | ||
309 | } | ||
310 | "#, | ||
311 | "j", | ||
312 | r#" | ||
313 | struct Foo { | ||
314 | j: i32, | ||
315 | } | ||
316 | |||
317 | impl Foo { | ||
318 | fn new(i: i32) -> Self { | ||
319 | Self { j: i } | ||
320 | } | ||
321 | } | ||
322 | "#, | ||
323 | ); | ||
324 | } | ||
325 | |||
326 | #[test] | ||
327 | fn test_rename_struct_field_for_shorthand() { | ||
328 | test_rename( | ||
329 | r#" | ||
330 | struct Foo { | ||
331 | i<|>: i32, | ||
332 | } | ||
333 | |||
334 | impl Foo { | ||
335 | fn new(i: i32) -> Self { | ||
336 | Self { i } | ||
337 | } | ||
338 | } | ||
339 | "#, | ||
340 | "j", | ||
341 | r#" | ||
342 | struct Foo { | ||
343 | j: i32, | ||
344 | } | ||
345 | |||
346 | impl Foo { | ||
347 | fn new(i: i32) -> Self { | ||
348 | Self { j: i } | ||
349 | } | ||
350 | } | ||
351 | "#, | ||
352 | ); | ||
353 | } | ||
354 | |||
355 | #[test] | ||
356 | fn test_rename_local_for_field_shorthand() { | ||
357 | test_rename( | ||
358 | r#" | ||
359 | struct Foo { | ||
360 | i: i32, | ||
361 | } | ||
362 | |||
363 | impl Foo { | ||
364 | fn new(i<|>: i32) -> Self { | ||
365 | Self { i } | ||
366 | } | ||
367 | } | ||
368 | "#, | ||
369 | "j", | ||
370 | r#" | ||
371 | struct Foo { | ||
372 | i: i32, | ||
373 | } | ||
374 | |||
375 | impl Foo { | ||
376 | fn new(j: i32) -> Self { | ||
377 | Self { i: j } | ||
378 | } | ||
379 | } | ||
380 | "#, | ||
381 | ); | ||
382 | } | ||
383 | |||
384 | #[test] | ||
385 | fn test_field_shorthand_correct_struct() { | ||
386 | test_rename( | ||
387 | r#" | ||
388 | struct Foo { | ||
389 | i<|>: i32, | ||
390 | } | ||
391 | |||
392 | struct Bar { | ||
393 | i: i32, | ||
394 | } | ||
395 | |||
396 | impl Bar { | ||
397 | fn new(i: i32) -> Self { | ||
398 | Self { i } | ||
399 | } | ||
400 | } | ||
401 | "#, | ||
402 | "j", | ||
403 | r#" | ||
404 | struct Foo { | ||
405 | j: i32, | ||
406 | } | ||
407 | |||
408 | struct Bar { | ||
409 | i: i32, | ||
410 | } | ||
411 | |||
412 | impl Bar { | ||
413 | fn new(i: i32) -> Self { | ||
414 | Self { i } | ||
415 | } | ||
416 | } | ||
417 | "#, | ||
418 | ); | ||
419 | } | ||
420 | |||
421 | #[test] | ||
422 | fn test_shadow_local_for_struct_shorthand() { | ||
423 | test_rename( | ||
424 | r#" | ||
425 | struct Foo { | ||
426 | i: i32, | ||
427 | } | ||
428 | |||
429 | fn baz(i<|>: i32) -> Self { | ||
430 | let x = Foo { i }; | ||
431 | { | ||
432 | let i = 0; | ||
433 | Foo { i } | ||
434 | } | ||
435 | } | ||
436 | "#, | ||
437 | "j", | ||
438 | r#" | ||
439 | struct Foo { | ||
440 | i: i32, | ||
441 | } | ||
442 | |||
443 | fn baz(j: i32) -> Self { | ||
444 | let x = Foo { i: j }; | ||
445 | { | ||
446 | let i = 0; | ||
447 | Foo { i } | ||
448 | } | ||
449 | } | ||
450 | "#, | ||
451 | ); | ||
452 | } | ||
453 | |||
454 | #[test] | ||
289 | fn test_rename_mod() { | 455 | fn test_rename_mod() { |
290 | let (analysis, position) = analysis_and_position( | 456 | let (analysis, position) = analysis_and_position( |
291 | " | 457 | " |