aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_ide/src/references/rename.rs100
-rw-r--r--crates/ra_ide_db/src/search.rs22
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::{
9use ra_text_edit::TextEdit; 9use ra_text_edit::TextEdit;
10 10
11use crate::{ 11use crate::{
12 FileId, FilePosition, FileSystemEdit, RangeInfo, SourceChange, SourceFileEdit, TextRange, 12 FilePosition, FileSystemEdit, RangeInfo, Reference, ReferenceKind, SourceChange,
13 SourceFileEdit, TextRange,
13}; 14};
14 15
15use super::find_all_refs; 16use 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
49fn source_edit_from_file_id_range( 50fn 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
57fn rename_mod( 66fn 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;
17use test_utils::tested_by; 17use test_utils::tested_by;
18 18
19use crate::{ 19use 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)]
32pub enum ReferenceKind { 32pub 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 }