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