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