diff options
Diffstat (limited to 'crates/ide/src/references')
-rw-r--r-- | crates/ide/src/references/rename.rs | 103 |
1 files changed, 52 insertions, 51 deletions
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs index 3edc43e08..c3ae568c2 100644 --- a/crates/ide/src/references/rename.rs +++ b/crates/ide/src/references/rename.rs | |||
@@ -1,14 +1,14 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | use std::{ | 2 | use std::{ |
3 | convert::TryInto, | 3 | convert::TryInto, |
4 | error::Error, | ||
5 | fmt::{self, Display}, | 4 | fmt::{self, Display}, |
6 | }; | 5 | }; |
7 | 6 | ||
8 | use hir::{Module, ModuleDef, ModuleSource, Semantics}; | 7 | use hir::{Module, ModuleDef, ModuleSource, Semantics}; |
9 | use ide_db::base_db::{AnchoredPathBuf, FileId, FileRange, SourceDatabaseExt}; | ||
10 | use ide_db::{ | 8 | use ide_db::{ |
9 | base_db::{AnchoredPathBuf, FileId, FileRange, SourceDatabaseExt}, | ||
11 | defs::{Definition, NameClass, NameRefClass}, | 10 | defs::{Definition, NameClass, NameRefClass}, |
11 | search::FileReference, | ||
12 | RootDatabase, | 12 | RootDatabase, |
13 | }; | 13 | }; |
14 | use syntax::{ | 14 | use syntax::{ |
@@ -20,8 +20,8 @@ use test_utils::mark; | |||
20 | use text_edit::TextEdit; | 20 | use text_edit::TextEdit; |
21 | 21 | ||
22 | use crate::{ | 22 | use crate::{ |
23 | FilePosition, FileSystemEdit, RangeInfo, Reference, ReferenceKind, ReferenceSearchResult, | 23 | FilePosition, FileSystemEdit, RangeInfo, ReferenceKind, ReferenceSearchResult, SourceChange, |
24 | SourceChange, SourceFileEdit, TextRange, TextSize, | 24 | SourceFileEdit, TextRange, TextSize, |
25 | }; | 25 | }; |
26 | 26 | ||
27 | type RenameResult<T> = Result<T, RenameError>; | 27 | type RenameResult<T> = Result<T, RenameError>; |
@@ -34,8 +34,6 @@ impl fmt::Display for RenameError { | |||
34 | } | 34 | } |
35 | } | 35 | } |
36 | 36 | ||
37 | impl Error for RenameError {} | ||
38 | |||
39 | macro_rules! format_err { | 37 | macro_rules! format_err { |
40 | ($fmt:expr) => {RenameError(format!($fmt))}; | 38 | ($fmt:expr) => {RenameError(format!($fmt))}; |
41 | ($fmt:expr, $($arg:tt)+) => {RenameError(format!($fmt, $($arg)+))} | 39 | ($fmt:expr, $($arg:tt)+) => {RenameError(format!($fmt, $($arg)+))} |
@@ -173,39 +171,46 @@ fn find_all_refs( | |||
173 | .ok_or_else(|| format_err!("No references found at position")) | 171 | .ok_or_else(|| format_err!("No references found at position")) |
174 | } | 172 | } |
175 | 173 | ||
176 | fn source_edit_from_reference( | 174 | fn source_edit_from_references( |
177 | sema: &Semantics<RootDatabase>, | 175 | sema: &Semantics<RootDatabase>, |
178 | reference: Reference, | 176 | file_id: FileId, |
177 | references: &[FileReference], | ||
179 | new_name: &str, | 178 | new_name: &str, |
180 | ) -> SourceFileEdit { | 179 | ) -> SourceFileEdit { |
181 | let mut replacement_text = String::new(); | 180 | let mut edit = TextEdit::builder(); |
182 | let range = match reference.kind { | 181 | for reference in references { |
183 | ReferenceKind::FieldShorthandForField => { | 182 | let mut replacement_text = String::new(); |
184 | mark::hit!(test_rename_struct_field_for_shorthand); | 183 | let range = match reference.kind { |
185 | replacement_text.push_str(new_name); | 184 | ReferenceKind::FieldShorthandForField => { |
186 | replacement_text.push_str(": "); | 185 | mark::hit!(test_rename_struct_field_for_shorthand); |
187 | TextRange::new(reference.file_range.range.start(), reference.file_range.range.start()) | 186 | replacement_text.push_str(new_name); |
188 | } | 187 | replacement_text.push_str(": "); |
189 | ReferenceKind::FieldShorthandForLocal => { | 188 | TextRange::new(reference.range.start(), reference.range.start()) |
190 | mark::hit!(test_rename_local_for_field_shorthand); | 189 | } |
191 | replacement_text.push_str(": "); | 190 | ReferenceKind::FieldShorthandForLocal => { |
192 | replacement_text.push_str(new_name); | 191 | mark::hit!(test_rename_local_for_field_shorthand); |
193 | TextRange::new(reference.file_range.range.end(), reference.file_range.range.end()) | 192 | replacement_text.push_str(": "); |
194 | } | 193 | replacement_text.push_str(new_name); |
195 | ReferenceKind::RecordFieldExprOrPat => { | 194 | TextRange::new(reference.range.end(), reference.range.end()) |
196 | mark::hit!(test_rename_field_expr_pat); | 195 | } |
197 | replacement_text.push_str(new_name); | 196 | ReferenceKind::RecordFieldExprOrPat => { |
198 | edit_text_range_for_record_field_expr_or_pat(sema, reference.file_range, new_name) | 197 | mark::hit!(test_rename_field_expr_pat); |
199 | } | 198 | replacement_text.push_str(new_name); |
200 | _ => { | 199 | edit_text_range_for_record_field_expr_or_pat( |
201 | replacement_text.push_str(new_name); | 200 | sema, |
202 | reference.file_range.range | 201 | FileRange { file_id, range: reference.range }, |
203 | } | 202 | new_name, |
204 | }; | 203 | ) |
205 | SourceFileEdit { | 204 | } |
206 | file_id: reference.file_range.file_id, | 205 | _ => { |
207 | edit: TextEdit::replace(range, replacement_text), | 206 | replacement_text.push_str(new_name); |
207 | reference.range | ||
208 | } | ||
209 | }; | ||
210 | edit.replace(range, replacement_text); | ||
208 | } | 211 | } |
212 | |||
213 | SourceFileEdit { file_id, edit: edit.finish() } | ||
209 | } | 214 | } |
210 | 215 | ||
211 | fn edit_text_range_for_record_field_expr_or_pat( | 216 | fn edit_text_range_for_record_field_expr_or_pat( |
@@ -276,10 +281,9 @@ fn rename_mod( | |||
276 | } | 281 | } |
277 | 282 | ||
278 | let RangeInfo { range, info: refs } = find_all_refs(sema, position)?; | 283 | let RangeInfo { range, info: refs } = find_all_refs(sema, position)?; |
279 | let ref_edits = refs | 284 | let ref_edits = refs.references().iter().map(|(&file_id, references)| { |
280 | .references | 285 | source_edit_from_references(sema, file_id, references, new_name) |
281 | .into_iter() | 286 | }); |
282 | .map(|reference| source_edit_from_reference(sema, reference, new_name)); | ||
283 | source_file_edits.extend(ref_edits); | 287 | source_file_edits.extend(ref_edits); |
284 | 288 | ||
285 | Ok(RangeInfo::new(range, SourceChange::from_edits(source_file_edits, file_system_edits))) | 289 | Ok(RangeInfo::new(range, SourceChange::from_edits(source_file_edits, file_system_edits))) |
@@ -331,17 +335,12 @@ fn rename_to_self( | |||
331 | 335 | ||
332 | let RangeInfo { range, info: refs } = find_all_refs(sema, position)?; | 336 | let RangeInfo { range, info: refs } = find_all_refs(sema, position)?; |
333 | 337 | ||
334 | let (param_ref, usages): (Vec<Reference>, Vec<Reference>) = refs | 338 | let mut edits = refs |
335 | .into_iter() | 339 | .references() |
336 | .partition(|reference| param_range.intersect(reference.file_range.range).is_some()); | 340 | .iter() |
337 | 341 | .map(|(&file_id, references)| { | |
338 | if param_ref.is_empty() { | 342 | source_edit_from_references(sema, file_id, references, "self") |
339 | bail!("Parameter to rename not found"); | 343 | }) |
340 | } | ||
341 | |||
342 | let mut edits = usages | ||
343 | .into_iter() | ||
344 | .map(|reference| source_edit_from_reference(sema, reference, "self")) | ||
345 | .collect::<Vec<_>>(); | 344 | .collect::<Vec<_>>(); |
346 | 345 | ||
347 | edits.push(SourceFileEdit { | 346 | edits.push(SourceFileEdit { |
@@ -467,7 +466,9 @@ fn rename_reference( | |||
467 | 466 | ||
468 | let edit = refs | 467 | let edit = refs |
469 | .into_iter() | 468 | .into_iter() |
470 | .map(|reference| source_edit_from_reference(sema, reference, new_name)) | 469 | .map(|(file_id, references)| { |
470 | source_edit_from_references(sema, file_id, &references, new_name) | ||
471 | }) | ||
471 | .collect::<Vec<_>>(); | 472 | .collect::<Vec<_>>(); |
472 | 473 | ||
473 | Ok(RangeInfo::new(range, SourceChange::from(edit))) | 474 | Ok(RangeInfo::new(range, SourceChange::from(edit))) |