]> git.lizzy.rs Git - rust.git/blob - crates/ide/src/rename.rs
a495e6c5432d93842ed2e6c0a0ed14d223422d2e
[rust.git] / crates / ide / src / rename.rs
1 //! Renaming functionality.
2 //!
3 //! This is mostly front-end for [`ide_db::rename`], but it also includes the
4 //! tests. This module also implements a couple of magic tricks, like renaming
5 //! `self` and to `self` (to switch between associated function and method).
6 use hir::{AsAssocItem, InFile, Semantics};
7 use ide_db::{
8     base_db::FileId,
9     defs::{Definition, NameClass, NameRefClass},
10     rename::{bail, format_err, source_edit_from_references, IdentifierKind},
11     RootDatabase,
12 };
13 use stdx::{always, never};
14 use syntax::{ast, AstNode, SyntaxNode};
15
16 use text_edit::TextEdit;
17
18 use crate::{FilePosition, RangeInfo, SourceChange};
19
20 pub use ide_db::rename::RenameError;
21
22 type RenameResult<T> = Result<T, RenameError>;
23
24 /// Prepares a rename. The sole job of this function is to return the TextRange of the thing that is
25 /// being targeted for a rename.
26 pub(crate) fn prepare_rename(
27     db: &RootDatabase,
28     position: FilePosition,
29 ) -> RenameResult<RangeInfo<()>> {
30     let sema = Semantics::new(db);
31     let source_file = sema.parse(position.file_id);
32     let syntax = source_file.syntax();
33
34     let (name_like, def) = find_definition(&sema, syntax, position)?;
35     if def.range_for_rename(&sema).is_none() {
36         bail!("No references found at position")
37     }
38
39     let frange = sema.original_range(name_like.syntax());
40     always!(frange.range.contains_inclusive(position.offset) && frange.file_id == position.file_id);
41     Ok(RangeInfo::new(frange.range, ()))
42 }
43
44 // Feature: Rename
45 //
46 // Renames the item below the cursor and all of its references
47 //
48 // |===
49 // | Editor  | Shortcut
50 //
51 // | VS Code | kbd:[F2]
52 // |===
53 //
54 // image::https://user-images.githubusercontent.com/48062697/113065582-055aae80-91b1-11eb-8ade-2b58e6d81883.gif[]
55 pub(crate) fn rename(
56     db: &RootDatabase,
57     position: FilePosition,
58     new_name: &str,
59 ) -> RenameResult<SourceChange> {
60     let sema = Semantics::new(db);
61     let source_file = sema.parse(position.file_id);
62     let syntax = source_file.syntax();
63
64     let (_name_like, def) = find_definition(&sema, syntax, position)?;
65
66     if let Definition::Local(local) = def {
67         if let Some(self_param) = local.as_self_param(sema.db) {
68             cov_mark::hit!(rename_self_to_param);
69             return rename_self_to_param(&sema, local, self_param, new_name);
70         }
71         if new_name == "self" {
72             cov_mark::hit!(rename_to_self);
73             return rename_to_self(&sema, local);
74         }
75     }
76
77     def.rename(&sema, new_name)
78 }
79
80 /// Called by the client when it is about to rename a file.
81 pub(crate) fn will_rename_file(
82     db: &RootDatabase,
83     file_id: FileId,
84     new_name_stem: &str,
85 ) -> Option<SourceChange> {
86     let sema = Semantics::new(db);
87     let module = sema.to_module_def(file_id)?;
88     let def = Definition::ModuleDef(module.into());
89     let mut change = def.rename(&sema, new_name_stem).ok()?;
90     change.file_system_edits.clear();
91     Some(change)
92 }
93
94 fn find_definition(
95     sema: &Semantics<RootDatabase>,
96     syntax: &SyntaxNode,
97     position: FilePosition,
98 ) -> RenameResult<(ast::NameLike, Definition)> {
99     let name_like = sema
100         .find_node_at_offset_with_descend::<ast::NameLike>(syntax, position.offset)
101         .ok_or_else(|| format_err!("No references found at position"))?;
102
103     let def = match &name_like {
104         // renaming aliases would rename the item being aliased as the HIR doesn't track aliases yet
105         ast::NameLike::Name(name)
106             if name.syntax().parent().map_or(false, |it| ast::Rename::can_cast(it.kind())) =>
107         {
108             bail!("Renaming aliases is currently unsupported")
109         }
110         ast::NameLike::Name(name) => NameClass::classify(sema, &name).map(|class| match class {
111             NameClass::Definition(it) | NameClass::ConstReference(it) => it,
112             NameClass::PatFieldShorthand { local_def, field_ref: _ } => {
113                 Definition::Local(local_def)
114             }
115         }),
116         ast::NameLike::NameRef(name_ref) => {
117             if let Some(def) = NameRefClass::classify(sema, &name_ref).map(|class| match class {
118                 NameRefClass::Definition(def) => def,
119                 NameRefClass::FieldShorthand { local_ref, field_ref: _ } => {
120                     Definition::Local(local_ref)
121                 }
122             }) {
123                 // if the name differs from the definitions name it has to be an alias
124                 if def.name(sema.db).map_or(false, |it| it.to_string() != name_ref.text()) {
125                     bail!("Renaming aliases is currently unsupported");
126                 }
127                 Some(def)
128             } else {
129                 None
130             }
131         }
132         ast::NameLike::Lifetime(lifetime) => NameRefClass::classify_lifetime(sema, &lifetime)
133             .and_then(|class| match class {
134                 NameRefClass::Definition(def) => Some(def),
135                 _ => None,
136             })
137             .or_else(|| {
138                 NameClass::classify_lifetime(sema, &lifetime).and_then(|it| match it {
139                     NameClass::Definition(it) => Some(it),
140                     _ => None,
141                 })
142             }),
143     }
144     .ok_or_else(|| format_err!("No references found at position"))?;
145
146     Ok((name_like, def))
147 }
148
149 fn rename_to_self(sema: &Semantics<RootDatabase>, local: hir::Local) -> RenameResult<SourceChange> {
150     if never!(local.is_self(sema.db)) {
151         bail!("rename_to_self invoked on self");
152     }
153
154     let fn_def = match local.parent(sema.db) {
155         hir::DefWithBody::Function(func) => func,
156         _ => bail!("Cannot rename local to self outside of function"),
157     };
158
159     if let Some(_) = fn_def.self_param(sema.db) {
160         bail!("Method already has a self parameter");
161     }
162
163     let params = fn_def.assoc_fn_params(sema.db);
164     let first_param = params
165         .first()
166         .ok_or_else(|| format_err!("Cannot rename local to self unless it is a parameter"))?;
167     if first_param.as_local(sema.db) != local {
168         bail!("Only the first parameter may be renamed to self");
169     }
170
171     let assoc_item = fn_def
172         .as_assoc_item(sema.db)
173         .ok_or_else(|| format_err!("Cannot rename parameter to self for free function"))?;
174     let impl_ = match assoc_item.container(sema.db) {
175         hir::AssocItemContainer::Trait(_) => {
176             bail!("Cannot rename parameter to self for trait functions");
177         }
178         hir::AssocItemContainer::Impl(impl_) => impl_,
179     };
180     let first_param_ty = first_param.ty();
181     let impl_ty = impl_.self_ty(sema.db);
182     let (ty, self_param) = if impl_ty.remove_ref().is_some() {
183         // if the impl is a ref to the type we can just match the `&T` with self directly
184         (first_param_ty.clone(), "self")
185     } else {
186         first_param_ty.remove_ref().map_or((first_param_ty.clone(), "self"), |ty| {
187             (ty, if first_param_ty.is_mutable_reference() { "&mut self" } else { "&self" })
188         })
189     };
190
191     if ty != impl_ty {
192         bail!("Parameter type differs from impl block type");
193     }
194
195     let InFile { file_id, value: param_source } =
196         first_param.source(sema.db).ok_or_else(|| format_err!("No source for parameter found"))?;
197
198     let def = Definition::Local(local);
199     let usages = def.usages(sema).all();
200     let mut source_change = SourceChange::default();
201     source_change.extend(usages.iter().map(|(&file_id, references)| {
202         (file_id, source_edit_from_references(references, def, "self"))
203     }));
204     source_change.insert_source_edit(
205         file_id.original_file(sema.db),
206         TextEdit::replace(param_source.syntax().text_range(), String::from(self_param)),
207     );
208     Ok(source_change)
209 }
210
211 fn rename_self_to_param(
212     sema: &Semantics<RootDatabase>,
213     local: hir::Local,
214     self_param: hir::SelfParam,
215     new_name: &str,
216 ) -> RenameResult<SourceChange> {
217     if new_name == "self" {
218         // Let's do nothing rather than complain.
219         cov_mark::hit!(rename_self_to_self);
220         return Ok(SourceChange::default());
221     }
222
223     let identifier_kind = IdentifierKind::classify(new_name)?;
224
225     let InFile { file_id, value: self_param } =
226         self_param.source(sema.db).ok_or_else(|| format_err!("cannot find function source"))?;
227
228     let def = Definition::Local(local);
229     let usages = def.usages(sema).all();
230     let edit = text_edit_from_self_param(&self_param, new_name)
231         .ok_or_else(|| format_err!("No target type found"))?;
232     if usages.len() > 1 && identifier_kind == IdentifierKind::Underscore {
233         bail!("Cannot rename reference to `_` as it is being referenced multiple times");
234     }
235     let mut source_change = SourceChange::default();
236     source_change.insert_source_edit(file_id.original_file(sema.db), edit);
237     source_change.extend(usages.iter().map(|(&file_id, references)| {
238         (file_id, source_edit_from_references(references, def, new_name))
239     }));
240     Ok(source_change)
241 }
242
243 fn text_edit_from_self_param(self_param: &ast::SelfParam, new_name: &str) -> Option<TextEdit> {
244     fn target_type_name(impl_def: &ast::Impl) -> Option<String> {
245         if let Some(ast::Type::PathType(p)) = impl_def.self_ty() {
246             return Some(p.path()?.segment()?.name_ref()?.text().to_string());
247         }
248         None
249     }
250
251     let impl_def = self_param.syntax().ancestors().find_map(ast::Impl::cast)?;
252     let type_name = target_type_name(&impl_def)?;
253
254     let mut replacement_text = String::from(new_name);
255     replacement_text.push_str(": ");
256     match (self_param.amp_token(), self_param.mut_token()) {
257         (Some(_), None) => replacement_text.push('&'),
258         (Some(_), Some(_)) => replacement_text.push_str("&mut "),
259         (_, _) => (),
260     };
261     replacement_text.push_str(type_name.as_str());
262
263     Some(TextEdit::replace(self_param.syntax().text_range(), replacement_text))
264 }
265
266 #[cfg(test)]
267 mod tests {
268     use expect_test::{expect, Expect};
269     use stdx::trim_indent;
270     use test_utils::assert_eq_text;
271     use text_edit::TextEdit;
272
273     use crate::{fixture, FileId};
274
275     use super::{RangeInfo, RenameError};
276
277     #[track_caller]
278     fn check(new_name: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
279         let ra_fixture_after = &trim_indent(ra_fixture_after);
280         let (analysis, position) = fixture::position(ra_fixture_before);
281         let rename_result = analysis
282             .rename(position, new_name)
283             .unwrap_or_else(|err| panic!("Rename to '{}' was cancelled: {}", new_name, err));
284         match rename_result {
285             Ok(source_change) => {
286                 let mut text_edit_builder = TextEdit::builder();
287                 let mut file_id: Option<FileId> = None;
288                 for edit in source_change.source_file_edits {
289                     file_id = Some(edit.0);
290                     for indel in edit.1.into_iter() {
291                         text_edit_builder.replace(indel.delete, indel.insert);
292                     }
293                 }
294                 if let Some(file_id) = file_id {
295                     let mut result = analysis.file_text(file_id).unwrap().to_string();
296                     text_edit_builder.finish().apply(&mut result);
297                     assert_eq_text!(ra_fixture_after, &*result);
298                 }
299             }
300             Err(err) => {
301                 if ra_fixture_after.starts_with("error:") {
302                     let error_message = ra_fixture_after
303                         .chars()
304                         .into_iter()
305                         .skip("error:".len())
306                         .collect::<String>();
307                     assert_eq!(error_message.trim(), err.to_string());
308                     return;
309                 } else {
310                     panic!("Rename to '{}' failed unexpectedly: {}", new_name, err)
311                 }
312             }
313         };
314     }
315
316     fn check_expect(new_name: &str, ra_fixture: &str, expect: Expect) {
317         let (analysis, position) = fixture::position(ra_fixture);
318         let source_change =
319             analysis.rename(position, new_name).unwrap().expect("Expect returned a RenameError");
320         expect.assert_debug_eq(&source_change)
321     }
322
323     fn check_prepare(ra_fixture: &str, expect: Expect) {
324         let (analysis, position) = fixture::position(ra_fixture);
325         let result = analysis
326             .prepare_rename(position)
327             .unwrap_or_else(|err| panic!("PrepareRename was cancelled: {}", err));
328         match result {
329             Ok(RangeInfo { range, info: () }) => {
330                 let source = analysis.file_text(position.file_id).unwrap();
331                 expect.assert_eq(&format!("{:?}: {}", range, &source[range]))
332             }
333             Err(RenameError(err)) => expect.assert_eq(&err),
334         };
335     }
336
337     #[test]
338     fn test_prepare_rename_namelikes() {
339         check_prepare(r"fn name$0<'lifetime>() {}", expect![[r#"3..7: name"#]]);
340         check_prepare(r"fn name<'lifetime$0>() {}", expect![[r#"8..17: 'lifetime"#]]);
341         check_prepare(r"fn name<'lifetime>() { name$0(); }", expect![[r#"23..27: name"#]]);
342     }
343
344     #[test]
345     fn test_prepare_rename_in_macro() {
346         check_prepare(
347             r"macro_rules! foo {
348     ($ident:ident) => {
349         pub struct $ident;
350     }
351 }
352 foo!(Foo$0);",
353             expect![[r#"83..86: Foo"#]],
354         );
355     }
356
357     #[test]
358     fn test_prepare_rename_keyword() {
359         check_prepare(r"struct$0 Foo;", expect![[r#"No references found at position"#]]);
360     }
361
362     #[test]
363     fn test_prepare_rename_tuple_field() {
364         check_prepare(
365             r#"
366 struct Foo(i32);
367
368 fn baz() {
369     let mut x = Foo(4);
370     x.0$0 = 5;
371 }
372 "#,
373             expect![[r#"No references found at position"#]],
374         );
375     }
376
377     #[test]
378     fn test_prepare_rename_builtin() {
379         check_prepare(
380             r#"
381 fn foo() {
382     let x: i32$0 = 0;
383 }
384 "#,
385             expect![[r#"No references found at position"#]],
386         );
387     }
388
389     #[test]
390     fn test_prepare_rename_self() {
391         check_prepare(
392             r#"
393 struct Foo {}
394
395 impl Foo {
396     fn foo(self) -> Self$0 {
397         self
398     }
399 }
400 "#,
401             expect![[r#"No references found at position"#]],
402         );
403     }
404
405     #[test]
406     fn test_rename_to_underscore() {
407         check("_", r#"fn main() { let i$0 = 1; }"#, r#"fn main() { let _ = 1; }"#);
408     }
409
410     #[test]
411     fn test_rename_to_raw_identifier() {
412         check("r#fn", r#"fn main() { let i$0 = 1; }"#, r#"fn main() { let r#fn = 1; }"#);
413     }
414
415     #[test]
416     fn test_rename_to_invalid_identifier1() {
417         check(
418             "invalid!",
419             r#"fn main() { let i$0 = 1; }"#,
420             "error: Invalid name `invalid!`: not an identifier",
421         );
422     }
423
424     #[test]
425     fn test_rename_to_invalid_identifier2() {
426         check(
427             "multiple tokens",
428             r#"fn main() { let i$0 = 1; }"#,
429             "error: Invalid name `multiple tokens`: not an identifier",
430         );
431     }
432
433     #[test]
434     fn test_rename_to_invalid_identifier3() {
435         check(
436             "let",
437             r#"fn main() { let i$0 = 1; }"#,
438             "error: Invalid name `let`: not an identifier",
439         );
440     }
441
442     #[test]
443     fn test_rename_to_invalid_identifier_lifetime() {
444         cov_mark::check!(rename_not_an_ident_ref);
445         check(
446             "'foo",
447             r#"fn main() { let i$0 = 1; }"#,
448             "error: Invalid name `'foo`: not an identifier",
449         );
450     }
451
452     #[test]
453     fn test_rename_to_invalid_identifier_lifetime2() {
454         cov_mark::check!(rename_not_a_lifetime_ident_ref);
455         check(
456             "foo",
457             r#"fn main<'a>(_: &'a$0 ()) {}"#,
458             "error: Invalid name `foo`: not a lifetime identifier",
459         );
460     }
461
462     #[test]
463     fn test_rename_to_underscore_invalid() {
464         cov_mark::check!(rename_underscore_multiple);
465         check(
466             "_",
467             r#"fn main(foo$0: ()) {foo;}"#,
468             "error: Cannot rename reference to `_` as it is being referenced multiple times",
469         );
470     }
471
472     #[test]
473     fn test_rename_mod_invalid() {
474         check(
475             "'foo",
476             r#"mod foo$0 {}"#,
477             "error: Invalid name `'foo`: cannot rename module to 'foo",
478         );
479     }
480
481     #[test]
482     fn test_rename_for_local() {
483         check(
484             "k",
485             r#"
486 fn main() {
487     let mut i = 1;
488     let j = 1;
489     i = i$0 + j;
490
491     { i = 0; }
492
493     i = 5;
494 }
495 "#,
496             r#"
497 fn main() {
498     let mut k = 1;
499     let j = 1;
500     k = k + j;
501
502     { k = 0; }
503
504     k = 5;
505 }
506 "#,
507         );
508     }
509
510     #[test]
511     fn test_rename_unresolved_reference() {
512         check(
513             "new_name",
514             r#"fn main() { let _ = unresolved_ref$0; }"#,
515             "error: No references found at position",
516         );
517     }
518
519     #[test]
520     fn test_rename_for_macro_args() {
521         check(
522             "b",
523             r#"
524 macro_rules! foo {($i:ident) => {$i} }
525 fn main() {
526     let a$0 = "test";
527     foo!(a);
528 }
529 "#,
530             r#"
531 macro_rules! foo {($i:ident) => {$i} }
532 fn main() {
533     let b = "test";
534     foo!(b);
535 }
536 "#,
537         );
538     }
539
540     #[test]
541     fn test_rename_for_macro_args_rev() {
542         check(
543             "b",
544             r#"
545 macro_rules! foo {($i:ident) => {$i} }
546 fn main() {
547     let a = "test";
548     foo!(a$0);
549 }
550 "#,
551             r#"
552 macro_rules! foo {($i:ident) => {$i} }
553 fn main() {
554     let b = "test";
555     foo!(b);
556 }
557 "#,
558         );
559     }
560
561     #[test]
562     fn test_rename_for_macro_define_fn() {
563         check(
564             "bar",
565             r#"
566 macro_rules! define_fn {($id:ident) => { fn $id{} }}
567 define_fn!(foo);
568 fn main() {
569     fo$0o();
570 }
571 "#,
572             r#"
573 macro_rules! define_fn {($id:ident) => { fn $id{} }}
574 define_fn!(bar);
575 fn main() {
576     bar();
577 }
578 "#,
579         );
580     }
581
582     #[test]
583     fn test_rename_for_macro_define_fn_rev() {
584         check(
585             "bar",
586             r#"
587 macro_rules! define_fn {($id:ident) => { fn $id{} }}
588 define_fn!(fo$0o);
589 fn main() {
590     foo();
591 }
592 "#,
593             r#"
594 macro_rules! define_fn {($id:ident) => { fn $id{} }}
595 define_fn!(bar);
596 fn main() {
597     bar();
598 }
599 "#,
600         );
601     }
602
603     #[test]
604     fn test_rename_for_param_inside() {
605         check("j", r#"fn foo(i : u32) -> u32 { i$0 }"#, r#"fn foo(j : u32) -> u32 { j }"#);
606     }
607
608     #[test]
609     fn test_rename_refs_for_fn_param() {
610         check("j", r#"fn foo(i$0 : u32) -> u32 { i }"#, r#"fn foo(j : u32) -> u32 { j }"#);
611     }
612
613     #[test]
614     fn test_rename_for_mut_param() {
615         check("j", r#"fn foo(mut i$0 : u32) -> u32 { i }"#, r#"fn foo(mut j : u32) -> u32 { j }"#);
616     }
617
618     #[test]
619     fn test_rename_struct_field() {
620         check(
621             "foo",
622             r#"
623 struct Foo { field$0: i32 }
624
625 impl Foo {
626     fn new(i: i32) -> Self {
627         Self { field: i }
628     }
629 }
630 "#,
631             r#"
632 struct Foo { foo: i32 }
633
634 impl Foo {
635     fn new(i: i32) -> Self {
636         Self { foo: i }
637     }
638 }
639 "#,
640         );
641     }
642
643     #[test]
644     fn test_rename_field_in_field_shorthand() {
645         cov_mark::check!(test_rename_field_in_field_shorthand);
646         check(
647             "field",
648             r#"
649 struct Foo { foo$0: i32 }
650
651 impl Foo {
652     fn new(foo: i32) -> Self {
653         Self { foo }
654     }
655 }
656 "#,
657             r#"
658 struct Foo { field: i32 }
659
660 impl Foo {
661     fn new(foo: i32) -> Self {
662         Self { field: foo }
663     }
664 }
665 "#,
666         );
667     }
668
669     #[test]
670     fn test_rename_local_in_field_shorthand() {
671         cov_mark::check!(test_rename_local_in_field_shorthand);
672         check(
673             "j",
674             r#"
675 struct Foo { i: i32 }
676
677 impl Foo {
678     fn new(i$0: i32) -> Self {
679         Self { i }
680     }
681 }
682 "#,
683             r#"
684 struct Foo { i: i32 }
685
686 impl Foo {
687     fn new(j: i32) -> Self {
688         Self { i: j }
689     }
690 }
691 "#,
692         );
693     }
694
695     #[test]
696     fn test_field_shorthand_correct_struct() {
697         check(
698             "j",
699             r#"
700 struct Foo { i$0: i32 }
701 struct Bar { i: i32 }
702
703 impl Bar {
704     fn new(i: i32) -> Self {
705         Self { i }
706     }
707 }
708 "#,
709             r#"
710 struct Foo { j: i32 }
711 struct Bar { i: i32 }
712
713 impl Bar {
714     fn new(i: i32) -> Self {
715         Self { i }
716     }
717 }
718 "#,
719         );
720     }
721
722     #[test]
723     fn test_shadow_local_for_struct_shorthand() {
724         check(
725             "j",
726             r#"
727 struct Foo { i: i32 }
728
729 fn baz(i$0: i32) -> Self {
730      let x = Foo { i };
731      {
732          let i = 0;
733          Foo { i }
734      }
735 }
736 "#,
737             r#"
738 struct Foo { i: i32 }
739
740 fn baz(j: i32) -> Self {
741      let x = Foo { i: j };
742      {
743          let i = 0;
744          Foo { i }
745      }
746 }
747 "#,
748         );
749     }
750
751     #[test]
752     fn test_rename_mod() {
753         check_expect(
754             "foo2",
755             r#"
756 //- /lib.rs
757 mod bar;
758
759 //- /bar.rs
760 mod foo$0;
761
762 //- /bar/foo.rs
763 // empty
764 "#,
765             expect![[r#"
766                 SourceChange {
767                     source_file_edits: {
768                         FileId(
769                             1,
770                         ): TextEdit {
771                             indels: [
772                                 Indel {
773                                     insert: "foo2",
774                                     delete: 4..7,
775                                 },
776                             ],
777                         },
778                     },
779                     file_system_edits: [
780                         MoveFile {
781                             src: FileId(
782                                 2,
783                             ),
784                             dst: AnchoredPathBuf {
785                                 anchor: FileId(
786                                     2,
787                                 ),
788                                 path: "foo2.rs",
789                             },
790                         },
791                     ],
792                     is_snippet: false,
793                 }
794             "#]],
795         );
796     }
797
798     #[test]
799     fn test_rename_mod_in_use_tree() {
800         check_expect(
801             "quux",
802             r#"
803 //- /main.rs
804 pub mod foo;
805 pub mod bar;
806 fn main() {}
807
808 //- /foo.rs
809 pub struct FooContent;
810
811 //- /bar.rs
812 use crate::foo$0::FooContent;
813 "#,
814             expect![[r#"
815                 SourceChange {
816                     source_file_edits: {
817                         FileId(
818                             0,
819                         ): TextEdit {
820                             indels: [
821                                 Indel {
822                                     insert: "quux",
823                                     delete: 8..11,
824                                 },
825                             ],
826                         },
827                         FileId(
828                             2,
829                         ): TextEdit {
830                             indels: [
831                                 Indel {
832                                     insert: "quux",
833                                     delete: 11..14,
834                                 },
835                             ],
836                         },
837                     },
838                     file_system_edits: [
839                         MoveFile {
840                             src: FileId(
841                                 1,
842                             ),
843                             dst: AnchoredPathBuf {
844                                 anchor: FileId(
845                                     1,
846                                 ),
847                                 path: "quux.rs",
848                             },
849                         },
850                     ],
851                     is_snippet: false,
852                 }
853             "#]],
854         );
855     }
856
857     #[test]
858     fn test_rename_mod_in_dir() {
859         check_expect(
860             "foo2",
861             r#"
862 //- /lib.rs
863 mod fo$0o;
864 //- /foo/mod.rs
865 // empty
866 "#,
867             expect![[r#"
868                 SourceChange {
869                     source_file_edits: {
870                         FileId(
871                             0,
872                         ): TextEdit {
873                             indels: [
874                                 Indel {
875                                     insert: "foo2",
876                                     delete: 4..7,
877                                 },
878                             ],
879                         },
880                     },
881                     file_system_edits: [
882                         MoveFile {
883                             src: FileId(
884                                 1,
885                             ),
886                             dst: AnchoredPathBuf {
887                                 anchor: FileId(
888                                     1,
889                                 ),
890                                 path: "../foo2/mod.rs",
891                             },
892                         },
893                     ],
894                     is_snippet: false,
895                 }
896             "#]],
897         );
898     }
899
900     #[test]
901     fn test_rename_unusually_nested_mod() {
902         check_expect(
903             "bar",
904             r#"
905 //- /lib.rs
906 mod outer { mod fo$0o; }
907
908 //- /outer/foo.rs
909 // empty
910 "#,
911             expect![[r#"
912                 SourceChange {
913                     source_file_edits: {
914                         FileId(
915                             0,
916                         ): TextEdit {
917                             indels: [
918                                 Indel {
919                                     insert: "bar",
920                                     delete: 16..19,
921                                 },
922                             ],
923                         },
924                     },
925                     file_system_edits: [
926                         MoveFile {
927                             src: FileId(
928                                 1,
929                             ),
930                             dst: AnchoredPathBuf {
931                                 anchor: FileId(
932                                     1,
933                                 ),
934                                 path: "bar.rs",
935                             },
936                         },
937                     ],
938                     is_snippet: false,
939                 }
940             "#]],
941         );
942     }
943
944     #[test]
945     fn test_module_rename_in_path() {
946         check(
947             "baz",
948             r#"
949 mod $0foo {
950     pub use self::bar as qux;
951     pub fn bar() {}
952 }
953
954 fn main() { foo::bar(); }
955 "#,
956             r#"
957 mod baz {
958     pub use self::bar as qux;
959     pub fn bar() {}
960 }
961
962 fn main() { baz::bar(); }
963 "#,
964         );
965     }
966
967     #[test]
968     fn test_rename_mod_filename_and_path() {
969         check_expect(
970             "foo2",
971             r#"
972 //- /lib.rs
973 mod bar;
974 fn f() {
975     bar::foo::fun()
976 }
977
978 //- /bar.rs
979 pub mod foo$0;
980
981 //- /bar/foo.rs
982 // pub fn fun() {}
983 "#,
984             expect![[r#"
985                 SourceChange {
986                     source_file_edits: {
987                         FileId(
988                             0,
989                         ): TextEdit {
990                             indels: [
991                                 Indel {
992                                     insert: "foo2",
993                                     delete: 27..30,
994                                 },
995                             ],
996                         },
997                         FileId(
998                             1,
999                         ): TextEdit {
1000                             indels: [
1001                                 Indel {
1002                                     insert: "foo2",
1003                                     delete: 8..11,
1004                                 },
1005                             ],
1006                         },
1007                     },
1008                     file_system_edits: [
1009                         MoveFile {
1010                             src: FileId(
1011                                 2,
1012                             ),
1013                             dst: AnchoredPathBuf {
1014                                 anchor: FileId(
1015                                     2,
1016                                 ),
1017                                 path: "foo2.rs",
1018                             },
1019                         },
1020                     ],
1021                     is_snippet: false,
1022                 }
1023             "#]],
1024         );
1025     }
1026
1027     #[test]
1028     fn test_enum_variant_from_module_1() {
1029         cov_mark::check!(rename_non_local);
1030         check(
1031             "Baz",
1032             r#"
1033 mod foo {
1034     pub enum Foo { Bar$0 }
1035 }
1036
1037 fn func(f: foo::Foo) {
1038     match f {
1039         foo::Foo::Bar => {}
1040     }
1041 }
1042 "#,
1043             r#"
1044 mod foo {
1045     pub enum Foo { Baz }
1046 }
1047
1048 fn func(f: foo::Foo) {
1049     match f {
1050         foo::Foo::Baz => {}
1051     }
1052 }
1053 "#,
1054         );
1055     }
1056
1057     #[test]
1058     fn test_enum_variant_from_module_2() {
1059         check(
1060             "baz",
1061             r#"
1062 mod foo {
1063     pub struct Foo { pub bar$0: uint }
1064 }
1065
1066 fn foo(f: foo::Foo) {
1067     let _ = f.bar;
1068 }
1069 "#,
1070             r#"
1071 mod foo {
1072     pub struct Foo { pub baz: uint }
1073 }
1074
1075 fn foo(f: foo::Foo) {
1076     let _ = f.baz;
1077 }
1078 "#,
1079         );
1080     }
1081
1082     #[test]
1083     fn test_parameter_to_self() {
1084         cov_mark::check!(rename_to_self);
1085         check(
1086             "self",
1087             r#"
1088 struct Foo { i: i32 }
1089
1090 impl Foo {
1091     fn f(foo$0: &mut Foo) -> i32 {
1092         foo.i
1093     }
1094 }
1095 "#,
1096             r#"
1097 struct Foo { i: i32 }
1098
1099 impl Foo {
1100     fn f(&mut self) -> i32 {
1101         self.i
1102     }
1103 }
1104 "#,
1105         );
1106         check(
1107             "self",
1108             r#"
1109 struct Foo { i: i32 }
1110
1111 impl Foo {
1112     fn f(foo$0: Foo) -> i32 {
1113         foo.i
1114     }
1115 }
1116 "#,
1117             r#"
1118 struct Foo { i: i32 }
1119
1120 impl Foo {
1121     fn f(self) -> i32 {
1122         self.i
1123     }
1124 }
1125 "#,
1126         );
1127     }
1128
1129     #[test]
1130     fn test_parameter_to_self_error_no_impl() {
1131         check(
1132             "self",
1133             r#"
1134 struct Foo { i: i32 }
1135
1136 fn f(foo$0: &mut Foo) -> i32 {
1137     foo.i
1138 }
1139 "#,
1140             "error: Cannot rename parameter to self for free function",
1141         );
1142         check(
1143             "self",
1144             r#"
1145 struct Foo { i: i32 }
1146 struct Bar;
1147
1148 impl Bar {
1149     fn f(foo$0: &mut Foo) -> i32 {
1150         foo.i
1151     }
1152 }
1153 "#,
1154             "error: Parameter type differs from impl block type",
1155         );
1156     }
1157
1158     #[test]
1159     fn test_parameter_to_self_error_not_first() {
1160         check(
1161             "self",
1162             r#"
1163 struct Foo { i: i32 }
1164 impl Foo {
1165     fn f(x: (), foo$0: &mut Foo) -> i32 {
1166         foo.i
1167     }
1168 }
1169 "#,
1170             "error: Only the first parameter may be renamed to self",
1171         );
1172     }
1173
1174     #[test]
1175     fn test_parameter_to_self_impl_ref() {
1176         check(
1177             "self",
1178             r#"
1179 struct Foo { i: i32 }
1180 impl &Foo {
1181     fn f(foo$0: &Foo) -> i32 {
1182         foo.i
1183     }
1184 }
1185 "#,
1186             r#"
1187 struct Foo { i: i32 }
1188 impl &Foo {
1189     fn f(self) -> i32 {
1190         self.i
1191     }
1192 }
1193 "#,
1194         );
1195     }
1196
1197     #[test]
1198     fn test_self_to_parameter() {
1199         check(
1200             "foo",
1201             r#"
1202 struct Foo { i: i32 }
1203
1204 impl Foo {
1205     fn f(&mut $0self) -> i32 {
1206         self.i
1207     }
1208 }
1209 "#,
1210             r#"
1211 struct Foo { i: i32 }
1212
1213 impl Foo {
1214     fn f(foo: &mut Foo) -> i32 {
1215         foo.i
1216     }
1217 }
1218 "#,
1219         );
1220     }
1221
1222     #[test]
1223     fn test_owned_self_to_parameter() {
1224         cov_mark::check!(rename_self_to_param);
1225         check(
1226             "foo",
1227             r#"
1228 struct Foo { i: i32 }
1229
1230 impl Foo {
1231     fn f($0self) -> i32 {
1232         self.i
1233     }
1234 }
1235 "#,
1236             r#"
1237 struct Foo { i: i32 }
1238
1239 impl Foo {
1240     fn f(foo: Foo) -> i32 {
1241         foo.i
1242     }
1243 }
1244 "#,
1245         );
1246     }
1247
1248     #[test]
1249     fn test_self_in_path_to_parameter() {
1250         check(
1251             "foo",
1252             r#"
1253 struct Foo { i: i32 }
1254
1255 impl Foo {
1256     fn f(&self) -> i32 {
1257         let self_var = 1;
1258         self$0.i
1259     }
1260 }
1261 "#,
1262             r#"
1263 struct Foo { i: i32 }
1264
1265 impl Foo {
1266     fn f(foo: &Foo) -> i32 {
1267         let self_var = 1;
1268         foo.i
1269     }
1270 }
1271 "#,
1272         );
1273     }
1274
1275     #[test]
1276     fn test_rename_field_put_init_shorthand() {
1277         cov_mark::check!(test_rename_field_put_init_shorthand);
1278         check(
1279             "bar",
1280             r#"
1281 struct Foo { i$0: i32 }
1282
1283 fn foo(bar: i32) -> Foo {
1284     Foo { i: bar }
1285 }
1286 "#,
1287             r#"
1288 struct Foo { bar: i32 }
1289
1290 fn foo(bar: i32) -> Foo {
1291     Foo { bar }
1292 }
1293 "#,
1294         );
1295     }
1296
1297     #[test]
1298     fn test_rename_local_put_init_shorthand() {
1299         cov_mark::check!(test_rename_local_put_init_shorthand);
1300         check(
1301             "i",
1302             r#"
1303 struct Foo { i: i32 }
1304
1305 fn foo(bar$0: i32) -> Foo {
1306     Foo { i: bar }
1307 }
1308 "#,
1309             r#"
1310 struct Foo { i: i32 }
1311
1312 fn foo(i: i32) -> Foo {
1313     Foo { i }
1314 }
1315 "#,
1316         );
1317     }
1318
1319     #[test]
1320     fn test_struct_field_pat_into_shorthand() {
1321         cov_mark::check!(test_rename_field_put_init_shorthand_pat);
1322         check(
1323             "baz",
1324             r#"
1325 struct Foo { i$0: i32 }
1326
1327 fn foo(foo: Foo) {
1328     let Foo { i: ref baz @ qux } = foo;
1329     let _ = qux;
1330 }
1331 "#,
1332             r#"
1333 struct Foo { baz: i32 }
1334
1335 fn foo(foo: Foo) {
1336     let Foo { baz: ref baz @ qux } = foo;
1337     let _ = qux;
1338 }
1339 "#,
1340         );
1341         check(
1342             "baz",
1343             r#"
1344 struct Foo { i$0: i32 }
1345
1346 fn foo(foo: Foo) {
1347     let Foo { i: ref baz } = foo;
1348     let _ = qux;
1349 }
1350 "#,
1351             r#"
1352 struct Foo { baz: i32 }
1353
1354 fn foo(foo: Foo) {
1355     let Foo { ref baz } = foo;
1356     let _ = qux;
1357 }
1358 "#,
1359         );
1360     }
1361
1362     #[test]
1363     fn test_struct_local_pat_into_shorthand() {
1364         cov_mark::check!(test_rename_local_put_init_shorthand_pat);
1365         check(
1366             "field",
1367             r#"
1368 struct Foo { field: i32 }
1369
1370 fn foo(foo: Foo) {
1371     let Foo { field: qux$0 } = foo;
1372     let _ = qux;
1373 }
1374 "#,
1375             r#"
1376 struct Foo { field: i32 }
1377
1378 fn foo(foo: Foo) {
1379     let Foo { field } = foo;
1380     let _ = field;
1381 }
1382 "#,
1383         );
1384         check(
1385             "field",
1386             r#"
1387 struct Foo { field: i32 }
1388
1389 fn foo(foo: Foo) {
1390     let Foo { field: x @ qux$0 } = foo;
1391     let _ = qux;
1392 }
1393 "#,
1394             r#"
1395 struct Foo { field: i32 }
1396
1397 fn foo(foo: Foo) {
1398     let Foo { field: x @ field } = foo;
1399     let _ = field;
1400 }
1401 "#,
1402         );
1403     }
1404
1405     #[test]
1406     fn test_rename_binding_in_destructure_pat() {
1407         let expected_fixture = r#"
1408 struct Foo {
1409     i: i32,
1410 }
1411
1412 fn foo(foo: Foo) {
1413     let Foo { i: bar } = foo;
1414     let _ = bar;
1415 }
1416 "#;
1417         check(
1418             "bar",
1419             r#"
1420 struct Foo {
1421     i: i32,
1422 }
1423
1424 fn foo(foo: Foo) {
1425     let Foo { i: b } = foo;
1426     let _ = b$0;
1427 }
1428 "#,
1429             expected_fixture,
1430         );
1431         check(
1432             "bar",
1433             r#"
1434 struct Foo {
1435     i: i32,
1436 }
1437
1438 fn foo(foo: Foo) {
1439     let Foo { i } = foo;
1440     let _ = i$0;
1441 }
1442 "#,
1443             expected_fixture,
1444         );
1445     }
1446
1447     #[test]
1448     fn test_rename_binding_in_destructure_param_pat() {
1449         check(
1450             "bar",
1451             r#"
1452 struct Foo {
1453     i: i32
1454 }
1455
1456 fn foo(Foo { i }: Foo) -> i32 {
1457     i$0
1458 }
1459 "#,
1460             r#"
1461 struct Foo {
1462     i: i32
1463 }
1464
1465 fn foo(Foo { i: bar }: Foo) -> i32 {
1466     bar
1467 }
1468 "#,
1469         )
1470     }
1471
1472     #[test]
1473     fn test_struct_field_complex_ident_pat() {
1474         cov_mark::check!(rename_record_pat_field_name_split);
1475         check(
1476             "baz",
1477             r#"
1478 struct Foo { i$0: i32 }
1479
1480 fn foo(foo: Foo) {
1481     let Foo { ref i } = foo;
1482 }
1483 "#,
1484             r#"
1485 struct Foo { baz: i32 }
1486
1487 fn foo(foo: Foo) {
1488     let Foo { baz: ref i } = foo;
1489 }
1490 "#,
1491         );
1492     }
1493
1494     #[test]
1495     fn test_rename_lifetimes() {
1496         cov_mark::check!(rename_lifetime);
1497         check(
1498             "'yeeee",
1499             r#"
1500 trait Foo<'a> {
1501     fn foo() -> &'a ();
1502 }
1503 impl<'a> Foo<'a> for &'a () {
1504     fn foo() -> &'a$0 () {
1505         unimplemented!()
1506     }
1507 }
1508 "#,
1509             r#"
1510 trait Foo<'a> {
1511     fn foo() -> &'a ();
1512 }
1513 impl<'yeeee> Foo<'yeeee> for &'yeeee () {
1514     fn foo() -> &'yeeee () {
1515         unimplemented!()
1516     }
1517 }
1518 "#,
1519         )
1520     }
1521
1522     #[test]
1523     fn test_rename_bind_pat() {
1524         check(
1525             "new_name",
1526             r#"
1527 fn main() {
1528     enum CustomOption<T> {
1529         None,
1530         Some(T),
1531     }
1532
1533     let test_variable = CustomOption::Some(22);
1534
1535     match test_variable {
1536         CustomOption::Some(foo$0) if foo == 11 => {}
1537         _ => (),
1538     }
1539 }"#,
1540             r#"
1541 fn main() {
1542     enum CustomOption<T> {
1543         None,
1544         Some(T),
1545     }
1546
1547     let test_variable = CustomOption::Some(22);
1548
1549     match test_variable {
1550         CustomOption::Some(new_name) if new_name == 11 => {}
1551         _ => (),
1552     }
1553 }"#,
1554         );
1555     }
1556
1557     #[test]
1558     fn test_rename_label() {
1559         check(
1560             "'foo",
1561             r#"
1562 fn foo<'a>() -> &'a () {
1563     'a: {
1564         'b: loop {
1565             break 'a$0;
1566         }
1567     }
1568 }
1569 "#,
1570             r#"
1571 fn foo<'a>() -> &'a () {
1572     'foo: {
1573         'b: loop {
1574             break 'foo;
1575         }
1576     }
1577 }
1578 "#,
1579         )
1580     }
1581
1582     #[test]
1583     fn test_self_to_self() {
1584         cov_mark::check!(rename_self_to_self);
1585         check(
1586             "self",
1587             r#"
1588 struct Foo;
1589 impl Foo {
1590     fn foo(self$0) {}
1591 }
1592 "#,
1593             r#"
1594 struct Foo;
1595 impl Foo {
1596     fn foo(self) {}
1597 }
1598 "#,
1599         )
1600     }
1601
1602     #[test]
1603     fn test_rename_field_in_pat_in_macro_doesnt_shorthand() {
1604         // ideally we would be able to make this emit a short hand, but I doubt this is easily possible
1605         check(
1606             "baz",
1607             r#"
1608 macro_rules! foo {
1609     ($pattern:pat) => {
1610         let $pattern = loop {};
1611     };
1612 }
1613 struct Foo {
1614     bar$0: u32,
1615 }
1616 fn foo() {
1617     foo!(Foo { bar: baz });
1618 }
1619 "#,
1620             r#"
1621 macro_rules! foo {
1622     ($pattern:pat) => {
1623         let $pattern = loop {};
1624     };
1625 }
1626 struct Foo {
1627     baz: u32,
1628 }
1629 fn foo() {
1630     foo!(Foo { baz: baz });
1631 }
1632 "#,
1633         )
1634     }
1635
1636     #[test]
1637     fn test_rename_tuple_field() {
1638         check(
1639             "foo",
1640             r#"
1641 struct Foo(i32);
1642
1643 fn baz() {
1644     let mut x = Foo(4);
1645     x.0$0 = 5;
1646 }
1647 "#,
1648             "error: No identifier available to rename",
1649         );
1650     }
1651
1652     #[test]
1653     fn test_rename_builtin() {
1654         check(
1655             "foo",
1656             r#"
1657 fn foo() {
1658     let x: i32$0 = 0;
1659 }
1660 "#,
1661             "error: Cannot rename builtin type",
1662         );
1663     }
1664
1665     #[test]
1666     fn test_rename_self() {
1667         check(
1668             "foo",
1669             r#"
1670 struct Foo {}
1671
1672 impl Foo {
1673     fn foo(self) -> Self$0 {
1674         self
1675     }
1676 }
1677 "#,
1678             "error: Cannot rename `Self`",
1679         );
1680     }
1681
1682     #[test]
1683     fn test_rename_ignores_self_ty() {
1684         check(
1685             "Fo0",
1686             r#"
1687 struct $0Foo;
1688
1689 impl Foo where Self: {}
1690 "#,
1691             r#"
1692 struct Fo0;
1693
1694 impl Fo0 where Self: {}
1695 "#,
1696         );
1697     }
1698
1699     #[test]
1700     fn test_rename_fails_on_aliases() {
1701         check(
1702             "Baz",
1703             r#"
1704 struct Foo;
1705 use Foo as Bar$0;
1706 "#,
1707             "error: Renaming aliases is currently unsupported",
1708         );
1709         check(
1710             "Baz",
1711             r#"
1712 struct Foo;
1713 use Foo as Bar;
1714 use Bar$0;
1715 "#,
1716             "error: Renaming aliases is currently unsupported",
1717         );
1718     }
1719
1720     #[test]
1721     fn test_rename_trait_method() {
1722         let res = r"
1723 trait Foo {
1724     fn foo(&self) {
1725         self.foo();
1726     }
1727 }
1728
1729 impl Foo for () {
1730     fn foo(&self) {
1731         self.foo();
1732     }
1733 }";
1734         check(
1735             "foo",
1736             r#"
1737 trait Foo {
1738     fn bar$0(&self) {
1739         self.bar();
1740     }
1741 }
1742
1743 impl Foo for () {
1744     fn bar(&self) {
1745         self.bar();
1746     }
1747 }"#,
1748             res,
1749         );
1750         check(
1751             "foo",
1752             r#"
1753 trait Foo {
1754     fn bar(&self) {
1755         self.bar$0();
1756     }
1757 }
1758
1759 impl Foo for () {
1760     fn bar(&self) {
1761         self.bar();
1762     }
1763 }"#,
1764             res,
1765         );
1766         check(
1767             "foo",
1768             r#"
1769 trait Foo {
1770     fn bar(&self) {
1771         self.bar();
1772     }
1773 }
1774
1775 impl Foo for () {
1776     fn bar$0(&self) {
1777         self.bar();
1778     }
1779 }"#,
1780             res,
1781         );
1782         check(
1783             "foo",
1784             r#"
1785 trait Foo {
1786     fn bar(&self) {
1787         self.bar();
1788     }
1789 }
1790
1791 impl Foo for () {
1792     fn bar(&self) {
1793         self.bar$0();
1794     }
1795 }"#,
1796             res,
1797         );
1798     }
1799
1800     #[test]
1801     fn test_rename_trait_method_prefix_of_second() {
1802         check(
1803             "qux",
1804             r#"
1805 trait Foo {
1806     fn foo$0() {}
1807     fn foobar() {}
1808 }
1809 "#,
1810             r#"
1811 trait Foo {
1812     fn qux() {}
1813     fn foobar() {}
1814 }
1815 "#,
1816         );
1817     }
1818
1819     #[test]
1820     fn test_rename_trait_const() {
1821         let res = r"
1822 trait Foo {
1823     const FOO: ();
1824 }
1825
1826 impl Foo for () {
1827     const FOO: ();
1828 }
1829 fn f() { <()>::FOO; }";
1830         check(
1831             "FOO",
1832             r#"
1833 trait Foo {
1834     const BAR$0: ();
1835 }
1836
1837 impl Foo for () {
1838     const BAR: ();
1839 }
1840 fn f() { <()>::BAR; }"#,
1841             res,
1842         );
1843         check(
1844             "FOO",
1845             r#"
1846 trait Foo {
1847     const BAR: ();
1848 }
1849
1850 impl Foo for () {
1851     const BAR$0: ();
1852 }
1853 fn f() { <()>::BAR; }"#,
1854             res,
1855         );
1856         check(
1857             "FOO",
1858             r#"
1859 trait Foo {
1860     const BAR: ();
1861 }
1862
1863 impl Foo for () {
1864     const BAR: ();
1865 }
1866 fn f() { <()>::BAR$0; }"#,
1867             res,
1868         );
1869     }
1870
1871     #[test]
1872     fn defs_from_macros_arent_renamed() {
1873         check(
1874             "lol",
1875             r#"
1876 macro_rules! m { () => { fn f() {} } }
1877 m!();
1878 fn main() { f$0()  }
1879 "#,
1880             "error: No identifier available to rename",
1881         )
1882     }
1883
1884     #[test]
1885     fn attributed_item() {
1886         check(
1887             "function",
1888             r#"
1889 //- proc_macros: identity
1890
1891 #[proc_macros::identity]
1892 fn func$0() {
1893     func();
1894 }
1895 "#,
1896             r#"
1897
1898 #[proc_macros::identity]
1899 fn function() {
1900     function();
1901 }
1902 "#,
1903         )
1904     }
1905 }