diff options
-rw-r--r-- | crates/ra_ide/src/references/rename.rs | 100 | ||||
-rw-r--r-- | crates/ra_ide_db/src/search.rs | 22 |
2 files changed, 96 insertions, 26 deletions
diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs index 5b4bcf434..794a109f3 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,20 @@ 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::from(new_name); |
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::StructFieldShorthand => { |
54 | SourceFileEdit { file_id, edit: TextEdit::replace(range, new_name.into()) } | 55 | replacement_text.push_str(": "); |
56 | TextRange::from_to( | ||
57 | reference.file_range.range.start(), | ||
58 | reference.file_range.range.start(), | ||
59 | ) | ||
60 | } | ||
61 | _ => reference.file_range.range, | ||
62 | }; | ||
63 | SourceFileEdit { file_id, edit: TextEdit::replace(range, replacement_text) } | ||
55 | } | 64 | } |
56 | 65 | ||
57 | fn rename_mod( | 66 | fn rename_mod( |
@@ -99,13 +108,10 @@ fn rename_mod( | |||
99 | source_file_edits.push(edit); | 108 | source_file_edits.push(edit); |
100 | 109 | ||
101 | if let Some(RangeInfo { range: _, info: refs }) = find_all_refs(sema.db, position, None) { | 110 | if let Some(RangeInfo { range: _, info: refs }) = find_all_refs(sema.db, position, None) { |
102 | let ref_edits = refs.references.into_iter().map(|reference| { | 111 | let ref_edits = refs |
103 | source_edit_from_file_id_range( | 112 | .references |
104 | reference.file_range.file_id, | 113 | .into_iter() |
105 | reference.file_range.range, | 114 | .map(|reference| source_edit_from_reference(reference, new_name)); |
106 | new_name, | ||
107 | ) | ||
108 | }); | ||
109 | source_file_edits.extend(ref_edits); | 115 | source_file_edits.extend(ref_edits); |
110 | } | 116 | } |
111 | 117 | ||
@@ -121,13 +127,7 @@ fn rename_reference( | |||
121 | 127 | ||
122 | let edit = refs | 128 | let edit = refs |
123 | .into_iter() | 129 | .into_iter() |
124 | .map(|reference| { | 130 | .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<_>>(); | 131 | .collect::<Vec<_>>(); |
132 | 132 | ||
133 | if edit.is_empty() { | 133 | if edit.is_empty() { |
@@ -286,6 +286,64 @@ mod tests { | |||
286 | } | 286 | } |
287 | 287 | ||
288 | #[test] | 288 | #[test] |
289 | fn test_rename_for_struct_field() { | ||
290 | test_rename( | ||
291 | r#" | ||
292 | struct Foo { | ||
293 | i<|>: i32, | ||
294 | } | ||
295 | |||
296 | impl Foo { | ||
297 | fn new(i: i32) -> Self { | ||
298 | Self { i: i } | ||
299 | } | ||
300 | } | ||
301 | "#, | ||
302 | "j", | ||
303 | r#" | ||
304 | struct Foo { | ||
305 | j: i32, | ||
306 | } | ||
307 | |||
308 | impl Foo { | ||
309 | fn new(i: i32) -> Self { | ||
310 | Self { j: i } | ||
311 | } | ||
312 | } | ||
313 | "#, | ||
314 | ); | ||
315 | } | ||
316 | |||
317 | #[test] | ||
318 | fn test_rename_for_struct_field_shorthand() { | ||
319 | test_rename( | ||
320 | r#" | ||
321 | struct Foo { | ||
322 | i<|>: i32, | ||
323 | } | ||
324 | |||
325 | impl Foo { | ||
326 | fn new(i: i32) -> Self { | ||
327 | Self { i } | ||
328 | } | ||
329 | } | ||
330 | "#, | ||
331 | "j", | ||
332 | r#" | ||
333 | struct Foo { | ||
334 | j: i32, | ||
335 | } | ||
336 | |||
337 | impl Foo { | ||
338 | fn new(i: i32) -> Self { | ||
339 | Self { j: i } | ||
340 | } | ||
341 | } | ||
342 | "#, | ||
343 | ); | ||
344 | } | ||
345 | |||
346 | #[test] | ||
289 | fn test_rename_mod() { | 347 | fn test_rename_mod() { |
290 | let (analysis, position) = analysis_and_position( | 348 | let (analysis, position) = analysis_and_position( |
291 | " | 349 | " |
diff --git a/crates/ra_ide_db/src/search.rs b/crates/ra_ide_db/src/search.rs index 6f198df04..9436a7562 100644 --- a/crates/ra_ide_db/src/search.rs +++ b/crates/ra_ide_db/src/search.rs | |||
@@ -17,7 +17,7 @@ use rustc_hash::FxHashMap; | |||
17 | use test_utils::tested_by; | 17 | use test_utils::tested_by; |
18 | 18 | ||
19 | use crate::{ | 19 | use crate::{ |
20 | defs::{classify_name_ref, Definition}, | 20 | defs::{classify_name_ref, Definition, NameRefClass}, |
21 | RootDatabase, | 21 | RootDatabase, |
22 | }; | 22 | }; |
23 | 23 | ||
@@ -30,6 +30,7 @@ pub struct Reference { | |||
30 | 30 | ||
31 | #[derive(Debug, Clone, PartialEq)] | 31 | #[derive(Debug, Clone, PartialEq)] |
32 | pub enum ReferenceKind { | 32 | pub enum ReferenceKind { |
33 | StructFieldShorthand, | ||
33 | StructLiteral, | 34 | StructLiteral, |
34 | Other, | 35 | Other, |
35 | } | 36 | } |
@@ -237,9 +238,8 @@ impl Definition { | |||
237 | // FIXME: reuse sb | 238 | // FIXME: reuse sb |
238 | // See https://github.com/rust-lang/rust/pull/68198#issuecomment-574269098 | 239 | // See https://github.com/rust-lang/rust/pull/68198#issuecomment-574269098 |
239 | 240 | ||
240 | if let Some(d) = classify_name_ref(&sema, &name_ref) { | 241 | match (classify_name_ref(&sema, &name_ref), self) { |
241 | let d = d.definition(); | 242 | (Some(NameRefClass::Definition(def)), _) if &def == self => { |
242 | if &d == self { | ||
243 | let kind = if is_record_lit_name_ref(&name_ref) | 243 | let kind = if is_record_lit_name_ref(&name_ref) |
244 | || is_call_expr_name_ref(&name_ref) | 244 | || is_call_expr_name_ref(&name_ref) |
245 | { | 245 | { |
@@ -252,9 +252,21 @@ impl Definition { | |||
252 | refs.push(Reference { | 252 | refs.push(Reference { |
253 | file_range, | 253 | file_range, |
254 | kind, | 254 | kind, |
255 | access: reference_access(&d, &name_ref), | 255 | access: reference_access(&def, &name_ref), |
256 | }); | 256 | }); |
257 | } | 257 | } |
258 | ( | ||
259 | Some(NameRefClass::FieldShorthand { local, field: _ }), | ||
260 | Definition::StructField(_), | ||
261 | ) => { | ||
262 | let file_range = sema.original_range(name_ref.syntax()); | ||
263 | refs.push(Reference { | ||
264 | file_range: file_range, | ||
265 | kind: ReferenceKind::StructFieldShorthand, | ||
266 | access: reference_access(&Definition::Local(local), &name_ref), | ||
267 | }); | ||
268 | } | ||
269 | _ => {} // not a usage | ||
258 | } | 270 | } |
259 | } | 271 | } |
260 | } | 272 | } |