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