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