]> git.lizzy.rs Git - rust.git/blob - crates/ide/src/references/rename.rs
Merge #6683
[rust.git] / crates / ide / src / references / rename.rs
1 //! FIXME: write short doc here
2 use std::{
3     convert::TryInto,
4     error::Error,
5     fmt::{self, Display},
6 };
7
8 use hir::{Module, ModuleDef, ModuleSource, Semantics};
9 use ide_db::base_db::{FileRange, SourceDatabaseExt};
10 use ide_db::{
11     defs::{Definition, NameClass, NameRefClass},
12     RootDatabase,
13 };
14 use syntax::{
15     algo::find_node_at_offset,
16     ast::{self, NameOwner},
17     lex_single_syntax_kind, match_ast, AstNode, SyntaxKind, SyntaxNode, SyntaxToken,
18 };
19 use test_utils::mark;
20 use text_edit::TextEdit;
21
22 use crate::{
23     references::find_all_refs, FilePosition, FileSystemEdit, RangeInfo, Reference, ReferenceKind,
24     SourceChange, SourceFileEdit, TextRange, TextSize,
25 };
26
27 #[derive(Debug)]
28 pub struct RenameError(pub(crate) String);
29
30 impl fmt::Display for RenameError {
31     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32         Display::fmt(&self.0, f)
33     }
34 }
35
36 impl Error for RenameError {}
37
38 pub(crate) fn rename(
39     db: &RootDatabase,
40     position: FilePosition,
41     new_name: &str,
42 ) -> Result<RangeInfo<SourceChange>, RenameError> {
43     let sema = Semantics::new(db);
44     rename_with_semantics(&sema, position, new_name)
45 }
46
47 pub(crate) fn rename_with_semantics(
48     sema: &Semantics<RootDatabase>,
49     position: FilePosition,
50     new_name: &str,
51 ) -> Result<RangeInfo<SourceChange>, RenameError> {
52     match lex_single_syntax_kind(new_name) {
53         Some(res) => match res {
54             (SyntaxKind::IDENT, _) => (),
55             (SyntaxKind::UNDERSCORE, _) => (),
56             (SyntaxKind::SELF_KW, _) => return rename_to_self(&sema, position),
57             (_, Some(syntax_error)) => {
58                 return Err(RenameError(format!("Invalid name `{}`: {}", new_name, syntax_error)))
59             }
60             (_, None) => {
61                 return Err(RenameError(format!("Invalid name `{}`: not an identifier", new_name)))
62             }
63         },
64         None => return Err(RenameError(format!("Invalid name `{}`: not an identifier", new_name))),
65     }
66
67     let source_file = sema.parse(position.file_id);
68     let syntax = source_file.syntax();
69     if let Some(module) = find_module_at_offset(&sema, position, syntax) {
70         rename_mod(&sema, position, module, new_name)
71     } else if let Some(self_token) =
72         syntax.token_at_offset(position.offset).find(|t| t.kind() == SyntaxKind::SELF_KW)
73     {
74         rename_self_to_param(&sema, position, self_token, new_name)
75     } else {
76         rename_reference(&sema, position, new_name)
77     }
78 }
79
80 fn find_module_at_offset(
81     sema: &Semantics<RootDatabase>,
82     position: FilePosition,
83     syntax: &SyntaxNode,
84 ) -> Option<Module> {
85     let ident = syntax.token_at_offset(position.offset).find(|t| t.kind() == SyntaxKind::IDENT)?;
86
87     let module = match_ast! {
88         match (ident.parent()) {
89             ast::NameRef(name_ref) => {
90                 match NameRefClass::classify(sema, &name_ref)? {
91                     NameRefClass::Definition(Definition::ModuleDef(ModuleDef::Module(module))) => module,
92                     _ => return None,
93                 }
94             },
95             ast::Name(name) => {
96                 match NameClass::classify(&sema, &name)? {
97                     NameClass::Definition(Definition::ModuleDef(ModuleDef::Module(module))) => module,
98                     _ => return None,
99                 }
100             },
101             _ => return None,
102         }
103     };
104
105     Some(module)
106 }
107
108 fn source_edit_from_reference(
109     sema: &Semantics<RootDatabase>,
110     reference: Reference,
111     new_name: &str,
112 ) -> SourceFileEdit {
113     let mut replacement_text = String::new();
114     let range = match reference.kind {
115         ReferenceKind::FieldShorthandForField => {
116             mark::hit!(test_rename_struct_field_for_shorthand);
117             replacement_text.push_str(new_name);
118             replacement_text.push_str(": ");
119             TextRange::new(reference.file_range.range.start(), reference.file_range.range.start())
120         }
121         ReferenceKind::FieldShorthandForLocal => {
122             mark::hit!(test_rename_local_for_field_shorthand);
123             replacement_text.push_str(": ");
124             replacement_text.push_str(new_name);
125             TextRange::new(reference.file_range.range.end(), reference.file_range.range.end())
126         }
127         ReferenceKind::RecordFieldExprOrPat => {
128             mark::hit!(test_rename_field_expr_pat);
129             replacement_text.push_str(new_name);
130             edit_text_range_for_record_field_expr_or_pat(sema, reference.file_range, new_name)
131         }
132         _ => {
133             replacement_text.push_str(new_name);
134             reference.file_range.range
135         }
136     };
137     SourceFileEdit {
138         file_id: reference.file_range.file_id,
139         edit: TextEdit::replace(range, replacement_text),
140     }
141 }
142
143 fn edit_text_range_for_record_field_expr_or_pat(
144     sema: &Semantics<RootDatabase>,
145     file_range: FileRange,
146     new_name: &str,
147 ) -> TextRange {
148     let source_file = sema.parse(file_range.file_id);
149     let file_syntax = source_file.syntax();
150     let original_range = file_range.range;
151
152     syntax::algo::find_node_at_range::<ast::RecordExprField>(file_syntax, original_range)
153         .and_then(|field_expr| match field_expr.expr().and_then(|e| e.name_ref()) {
154             Some(name) if &name.to_string() == new_name => Some(field_expr.syntax().text_range()),
155             _ => None,
156         })
157         .or_else(|| {
158             syntax::algo::find_node_at_range::<ast::RecordPatField>(file_syntax, original_range)
159                 .and_then(|field_pat| match field_pat.pat() {
160                     Some(ast::Pat::IdentPat(pat))
161                         if pat.name().map(|n| n.to_string()).as_deref() == Some(new_name) =>
162                     {
163                         Some(field_pat.syntax().text_range())
164                     }
165                     _ => None,
166                 })
167         })
168         .unwrap_or(original_range)
169 }
170
171 fn rename_mod(
172     sema: &Semantics<RootDatabase>,
173     position: FilePosition,
174     module: Module,
175     new_name: &str,
176 ) -> Result<RangeInfo<SourceChange>, RenameError> {
177     let mut source_file_edits = Vec::new();
178     let mut file_system_edits = Vec::new();
179
180     let src = module.definition_source(sema.db);
181     let file_id = src.file_id.original_file(sema.db);
182     match src.value {
183         ModuleSource::SourceFile(..) => {
184             // mod is defined in path/to/dir/mod.rs
185             let dst = if module.is_mod_rs(sema.db) {
186                 format!("../{}/mod.rs", new_name)
187             } else {
188                 format!("{}.rs", new_name)
189             };
190             let move_file = FileSystemEdit::MoveFile { src: file_id, anchor: file_id, dst };
191             file_system_edits.push(move_file);
192         }
193         ModuleSource::Module(..) => {}
194     }
195
196     if let Some(src) = module.declaration_source(sema.db) {
197         let file_id = src.file_id.original_file(sema.db);
198         let name = src.value.name().unwrap();
199         let edit = SourceFileEdit {
200             file_id,
201             edit: TextEdit::replace(name.syntax().text_range(), new_name.into()),
202         };
203         source_file_edits.push(edit);
204     }
205
206     let RangeInfo { range, info: refs } = find_all_refs(sema, position, None)
207         .ok_or_else(|| RenameError("No references found at position".to_string()))?;
208     let ref_edits = refs
209         .references
210         .into_iter()
211         .map(|reference| source_edit_from_reference(sema, reference, new_name));
212     source_file_edits.extend(ref_edits);
213
214     Ok(RangeInfo::new(range, SourceChange::from_edits(source_file_edits, file_system_edits)))
215 }
216
217 fn rename_to_self(
218     sema: &Semantics<RootDatabase>,
219     position: FilePosition,
220 ) -> Result<RangeInfo<SourceChange>, RenameError> {
221     let source_file = sema.parse(position.file_id);
222     let syn = source_file.syntax();
223
224     let (fn_def, fn_ast) = find_node_at_offset::<ast::Fn>(syn, position.offset)
225         .and_then(|fn_ast| sema.to_def(&fn_ast).zip(Some(fn_ast)))
226         .ok_or_else(|| RenameError("No surrounding method declaration found".to_string()))?;
227     let param_range = fn_ast
228         .param_list()
229         .and_then(|p| p.params().next())
230         .ok_or_else(|| RenameError("Method has no parameters".to_string()))?
231         .syntax()
232         .text_range();
233     if !param_range.contains(position.offset) {
234         return Err(RenameError("Only the first parameter can be self".to_string()));
235     }
236
237     let impl_block = find_node_at_offset::<ast::Impl>(syn, position.offset)
238         .and_then(|def| sema.to_def(&def))
239         .ok_or_else(|| RenameError("No impl block found for function".to_string()))?;
240     if fn_def.self_param(sema.db).is_some() {
241         return Err(RenameError("Method already has a self parameter".to_string()));
242     }
243
244     let params = fn_def.assoc_fn_params(sema.db);
245     let first_param =
246         params.first().ok_or_else(|| RenameError("Method has no parameters".into()))?;
247     let first_param_ty = first_param.ty();
248     let impl_ty = impl_block.target_ty(sema.db);
249     let (ty, self_param) = if impl_ty.remove_ref().is_some() {
250         // if the impl is a ref to the type we can just match the `&T` with self directly
251         (first_param_ty.clone(), "self")
252     } else {
253         first_param_ty.remove_ref().map_or((first_param_ty.clone(), "self"), |ty| {
254             (ty, if first_param_ty.is_mutable_reference() { "&mut self" } else { "&self" })
255         })
256     };
257
258     if ty != impl_ty {
259         return Err(RenameError("Parameter type differs from impl block type".to_string()));
260     }
261
262     let RangeInfo { range, info: refs } = find_all_refs(sema, position, None)
263         .ok_or_else(|| RenameError("No reference found at position".to_string()))?;
264
265     let (param_ref, usages): (Vec<Reference>, Vec<Reference>) = refs
266         .into_iter()
267         .partition(|reference| param_range.intersect(reference.file_range.range).is_some());
268
269     if param_ref.is_empty() {
270         return Err(RenameError("Parameter to rename not found".to_string()));
271     }
272
273     let mut edits = usages
274         .into_iter()
275         .map(|reference| source_edit_from_reference(sema, reference, "self"))
276         .collect::<Vec<_>>();
277
278     edits.push(SourceFileEdit {
279         file_id: position.file_id,
280         edit: TextEdit::replace(param_range, String::from(self_param)),
281     });
282
283     Ok(RangeInfo::new(range, SourceChange::from(edits)))
284 }
285
286 fn text_edit_from_self_param(
287     syn: &SyntaxNode,
288     self_param: &ast::SelfParam,
289     new_name: &str,
290 ) -> Option<TextEdit> {
291     fn target_type_name(impl_def: &ast::Impl) -> Option<String> {
292         if let Some(ast::Type::PathType(p)) = impl_def.self_ty() {
293             return Some(p.path()?.segment()?.name_ref()?.text().to_string());
294         }
295         None
296     }
297
298     let impl_def = find_node_at_offset::<ast::Impl>(syn, self_param.syntax().text_range().start())?;
299     let type_name = target_type_name(&impl_def)?;
300
301     let mut replacement_text = String::from(new_name);
302     replacement_text.push_str(": ");
303     match (self_param.amp_token(), self_param.mut_token()) {
304         (None, None) => (),
305         (Some(_), None) => replacement_text.push('&'),
306         (_, Some(_)) => replacement_text.push_str("&mut "),
307     };
308     replacement_text.push_str(type_name.as_str());
309
310     Some(TextEdit::replace(self_param.syntax().text_range(), replacement_text))
311 }
312
313 fn rename_self_to_param(
314     sema: &Semantics<RootDatabase>,
315     position: FilePosition,
316     self_token: SyntaxToken,
317     new_name: &str,
318 ) -> Result<RangeInfo<SourceChange>, RenameError> {
319     let source_file = sema.parse(position.file_id);
320     let syn = source_file.syntax();
321
322     let text = sema.db.file_text(position.file_id);
323     let fn_def = find_node_at_offset::<ast::Fn>(syn, position.offset)
324         .ok_or_else(|| RenameError("No surrounding method declaration found".to_string()))?;
325     let search_range = fn_def.syntax().text_range();
326
327     let mut edits: Vec<SourceFileEdit> = vec![];
328
329     for (idx, _) in text.match_indices("self") {
330         let offset: TextSize = idx.try_into().unwrap();
331         if !search_range.contains_inclusive(offset) {
332             continue;
333         }
334         if let Some(ref usage) =
335             syn.token_at_offset(offset).find(|t| t.kind() == SyntaxKind::SELF_KW)
336         {
337             let edit = if let Some(ref self_param) = ast::SelfParam::cast(usage.parent()) {
338                 text_edit_from_self_param(syn, self_param, new_name)
339                     .ok_or_else(|| RenameError("No target type found".to_string()))?
340             } else {
341                 TextEdit::replace(usage.text_range(), String::from(new_name))
342             };
343             edits.push(SourceFileEdit { file_id: position.file_id, edit });
344         }
345     }
346
347     let range = ast::SelfParam::cast(self_token.parent())
348         .map_or(self_token.text_range(), |p| p.syntax().text_range());
349
350     Ok(RangeInfo::new(range, SourceChange::from(edits)))
351 }
352
353 fn rename_reference(
354     sema: &Semantics<RootDatabase>,
355     position: FilePosition,
356     new_name: &str,
357 ) -> Result<RangeInfo<SourceChange>, RenameError> {
358     let RangeInfo { range, info: refs } = match find_all_refs(sema, position, None) {
359         Some(range_info) => range_info,
360         None => return Err(RenameError("No references found at position".to_string())),
361     };
362
363     let edit = refs
364         .into_iter()
365         .map(|reference| source_edit_from_reference(sema, reference, new_name))
366         .collect::<Vec<_>>();
367
368     if edit.is_empty() {
369         return Err(RenameError("No references found at position".to_string()));
370     }
371
372     Ok(RangeInfo::new(range, SourceChange::from(edit)))
373 }
374
375 #[cfg(test)]
376 mod tests {
377     use expect_test::{expect, Expect};
378     use stdx::trim_indent;
379     use test_utils::{assert_eq_text, mark};
380     use text_edit::TextEdit;
381
382     use crate::{fixture, FileId};
383
384     fn check(new_name: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
385         let ra_fixture_after = &trim_indent(ra_fixture_after);
386         let (analysis, position) = fixture::position(ra_fixture_before);
387         let rename_result = analysis
388             .rename(position, new_name)
389             .unwrap_or_else(|err| panic!("Rename to '{}' was cancelled: {}", new_name, err));
390         match rename_result {
391             Ok(source_change) => {
392                 let mut text_edit_builder = TextEdit::builder();
393                 let mut file_id: Option<FileId> = None;
394                 for edit in source_change.info.source_file_edits {
395                     file_id = Some(edit.file_id);
396                     for indel in edit.edit.into_iter() {
397                         text_edit_builder.replace(indel.delete, indel.insert);
398                     }
399                 }
400                 let mut result = analysis.file_text(file_id.unwrap()).unwrap().to_string();
401                 text_edit_builder.finish().apply(&mut result);
402                 assert_eq_text!(ra_fixture_after, &*result);
403             }
404             Err(err) => {
405                 if ra_fixture_after.starts_with("error:") {
406                     let error_message = ra_fixture_after
407                         .chars()
408                         .into_iter()
409                         .skip("error:".len())
410                         .collect::<String>();
411                     assert_eq!(error_message.trim(), err.to_string());
412                     return;
413                 } else {
414                     panic!("Rename to '{}' failed unexpectedly: {}", new_name, err)
415                 }
416             }
417         };
418     }
419
420     fn check_expect(new_name: &str, ra_fixture: &str, expect: Expect) {
421         let (analysis, position) = fixture::position(ra_fixture);
422         let source_change = analysis
423             .rename(position, new_name)
424             .unwrap()
425             .expect("Expect returned RangeInfo to be Some, but was None");
426         expect.assert_debug_eq(&source_change)
427     }
428
429     #[test]
430     fn test_rename_to_underscore() {
431         check("_", r#"fn main() { let i<|> = 1; }"#, r#"fn main() { let _ = 1; }"#);
432     }
433
434     #[test]
435     fn test_rename_to_raw_identifier() {
436         check("r#fn", r#"fn main() { let i<|> = 1; }"#, r#"fn main() { let r#fn = 1; }"#);
437     }
438
439     #[test]
440     fn test_rename_to_invalid_identifier1() {
441         check(
442             "invalid!",
443             r#"fn main() { let i<|> = 1; }"#,
444             "error: Invalid name `invalid!`: not an identifier",
445         );
446     }
447
448     #[test]
449     fn test_rename_to_invalid_identifier2() {
450         check(
451             "multiple tokens",
452             r#"fn main() { let i<|> = 1; }"#,
453             "error: Invalid name `multiple tokens`: not an identifier",
454         );
455     }
456
457     #[test]
458     fn test_rename_to_invalid_identifier3() {
459         check(
460             "let",
461             r#"fn main() { let i<|> = 1; }"#,
462             "error: Invalid name `let`: not an identifier",
463         );
464     }
465
466     #[test]
467     fn test_rename_for_local() {
468         check(
469             "k",
470             r#"
471 fn main() {
472     let mut i = 1;
473     let j = 1;
474     i = i<|> + j;
475
476     { i = 0; }
477
478     i = 5;
479 }
480 "#,
481             r#"
482 fn main() {
483     let mut k = 1;
484     let j = 1;
485     k = k + j;
486
487     { k = 0; }
488
489     k = 5;
490 }
491 "#,
492         );
493     }
494
495     #[test]
496     fn test_rename_unresolved_reference() {
497         check(
498             "new_name",
499             r#"fn main() { let _ = unresolved_ref<|>; }"#,
500             "error: No references found at position",
501         );
502     }
503
504     #[test]
505     fn test_rename_for_macro_args() {
506         check(
507             "b",
508             r#"
509 macro_rules! foo {($i:ident) => {$i} }
510 fn main() {
511     let a<|> = "test";
512     foo!(a);
513 }
514 "#,
515             r#"
516 macro_rules! foo {($i:ident) => {$i} }
517 fn main() {
518     let b = "test";
519     foo!(b);
520 }
521 "#,
522         );
523     }
524
525     #[test]
526     fn test_rename_for_macro_args_rev() {
527         check(
528             "b",
529             r#"
530 macro_rules! foo {($i:ident) => {$i} }
531 fn main() {
532     let a = "test";
533     foo!(a<|>);
534 }
535 "#,
536             r#"
537 macro_rules! foo {($i:ident) => {$i} }
538 fn main() {
539     let b = "test";
540     foo!(b);
541 }
542 "#,
543         );
544     }
545
546     #[test]
547     fn test_rename_for_macro_define_fn() {
548         check(
549             "bar",
550             r#"
551 macro_rules! define_fn {($id:ident) => { fn $id{} }}
552 define_fn!(foo);
553 fn main() {
554     fo<|>o();
555 }
556 "#,
557             r#"
558 macro_rules! define_fn {($id:ident) => { fn $id{} }}
559 define_fn!(bar);
560 fn main() {
561     bar();
562 }
563 "#,
564         );
565     }
566
567     #[test]
568     fn test_rename_for_macro_define_fn_rev() {
569         check(
570             "bar",
571             r#"
572 macro_rules! define_fn {($id:ident) => { fn $id{} }}
573 define_fn!(fo<|>o);
574 fn main() {
575     foo();
576 }
577 "#,
578             r#"
579 macro_rules! define_fn {($id:ident) => { fn $id{} }}
580 define_fn!(bar);
581 fn main() {
582     bar();
583 }
584 "#,
585         );
586     }
587
588     #[test]
589     fn test_rename_for_param_inside() {
590         check("j", r#"fn foo(i : u32) -> u32 { i<|> }"#, r#"fn foo(j : u32) -> u32 { j }"#);
591     }
592
593     #[test]
594     fn test_rename_refs_for_fn_param() {
595         check("j", r#"fn foo(i<|> : u32) -> u32 { i }"#, r#"fn foo(j : u32) -> u32 { j }"#);
596     }
597
598     #[test]
599     fn test_rename_for_mut_param() {
600         check("j", r#"fn foo(mut i<|> : u32) -> u32 { i }"#, r#"fn foo(mut j : u32) -> u32 { j }"#);
601     }
602
603     #[test]
604     fn test_rename_struct_field() {
605         check(
606             "j",
607             r#"
608 struct Foo { i<|>: i32 }
609
610 impl Foo {
611     fn new(i: i32) -> Self {
612         Self { i: i }
613     }
614 }
615 "#,
616             r#"
617 struct Foo { j: i32 }
618
619 impl Foo {
620     fn new(i: i32) -> Self {
621         Self { j: i }
622     }
623 }
624 "#,
625         );
626     }
627
628     #[test]
629     fn test_rename_struct_field_for_shorthand() {
630         mark::check!(test_rename_struct_field_for_shorthand);
631         check(
632             "j",
633             r#"
634 struct Foo { i<|>: i32 }
635
636 impl Foo {
637     fn new(i: i32) -> Self {
638         Self { i }
639     }
640 }
641 "#,
642             r#"
643 struct Foo { j: i32 }
644
645 impl Foo {
646     fn new(i: i32) -> Self {
647         Self { j: i }
648     }
649 }
650 "#,
651         );
652     }
653
654     #[test]
655     fn test_rename_local_for_field_shorthand() {
656         mark::check!(test_rename_local_for_field_shorthand);
657         check(
658             "j",
659             r#"
660 struct Foo { i: i32 }
661
662 impl Foo {
663     fn new(i<|>: i32) -> Self {
664         Self { i }
665     }
666 }
667 "#,
668             r#"
669 struct Foo { i: i32 }
670
671 impl Foo {
672     fn new(j: i32) -> Self {
673         Self { i: j }
674     }
675 }
676 "#,
677         );
678     }
679
680     #[test]
681     fn test_field_shorthand_correct_struct() {
682         check(
683             "j",
684             r#"
685 struct Foo { i<|>: i32 }
686 struct Bar { i: i32 }
687
688 impl Bar {
689     fn new(i: i32) -> Self {
690         Self { i }
691     }
692 }
693 "#,
694             r#"
695 struct Foo { j: i32 }
696 struct Bar { i: i32 }
697
698 impl Bar {
699     fn new(i: i32) -> Self {
700         Self { i }
701     }
702 }
703 "#,
704         );
705     }
706
707     #[test]
708     fn test_shadow_local_for_struct_shorthand() {
709         check(
710             "j",
711             r#"
712 struct Foo { i: i32 }
713
714 fn baz(i<|>: i32) -> Self {
715      let x = Foo { i };
716      {
717          let i = 0;
718          Foo { i }
719      }
720 }
721 "#,
722             r#"
723 struct Foo { i: i32 }
724
725 fn baz(j: i32) -> Self {
726      let x = Foo { i: j };
727      {
728          let i = 0;
729          Foo { i }
730      }
731 }
732 "#,
733         );
734     }
735
736     #[test]
737     fn test_rename_mod() {
738         check_expect(
739             "foo2",
740             r#"
741 //- /lib.rs
742 mod bar;
743
744 //- /bar.rs
745 mod foo<|>;
746
747 //- /bar/foo.rs
748 // empty
749 "#,
750             expect![[r#"
751                 RangeInfo {
752                     range: 4..7,
753                     info: SourceChange {
754                         source_file_edits: [
755                             SourceFileEdit {
756                                 file_id: FileId(
757                                     1,
758                                 ),
759                                 edit: TextEdit {
760                                     indels: [
761                                         Indel {
762                                             insert: "foo2",
763                                             delete: 4..7,
764                                         },
765                                     ],
766                                 },
767                             },
768                         ],
769                         file_system_edits: [
770                             MoveFile {
771                                 src: FileId(
772                                     2,
773                                 ),
774                                 anchor: FileId(
775                                     2,
776                                 ),
777                                 dst: "foo2.rs",
778                             },
779                         ],
780                         is_snippet: false,
781                     },
782                 }
783             "#]],
784         );
785     }
786
787     #[test]
788     fn test_rename_mod_in_use_tree() {
789         check_expect(
790             "quux",
791             r#"
792 //- /main.rs
793 pub mod foo;
794 pub mod bar;
795 fn main() {}
796
797 //- /foo.rs
798 pub struct FooContent;
799
800 //- /bar.rs
801 use crate::foo<|>::FooContent;
802 "#,
803             expect![[r#"
804                 RangeInfo {
805                     range: 11..14,
806                     info: SourceChange {
807                         source_file_edits: [
808                             SourceFileEdit {
809                                 file_id: FileId(
810                                     0,
811                                 ),
812                                 edit: TextEdit {
813                                     indels: [
814                                         Indel {
815                                             insert: "quux",
816                                             delete: 8..11,
817                                         },
818                                     ],
819                                 },
820                             },
821                             SourceFileEdit {
822                                 file_id: FileId(
823                                     2,
824                                 ),
825                                 edit: TextEdit {
826                                     indels: [
827                                         Indel {
828                                             insert: "quux",
829                                             delete: 11..14,
830                                         },
831                                     ],
832                                 },
833                             },
834                         ],
835                         file_system_edits: [
836                             MoveFile {
837                                 src: FileId(
838                                     1,
839                                 ),
840                                 anchor: FileId(
841                                     1,
842                                 ),
843                                 dst: "quux.rs",
844                             },
845                         ],
846                         is_snippet: false,
847                     },
848                 }
849             "#]],
850         );
851     }
852
853     #[test]
854     fn test_rename_mod_in_dir() {
855         check_expect(
856             "foo2",
857             r#"
858 //- /lib.rs
859 mod fo<|>o;
860 //- /foo/mod.rs
861 // emtpy
862 "#,
863             expect![[r#"
864                 RangeInfo {
865                     range: 4..7,
866                     info: SourceChange {
867                         source_file_edits: [
868                             SourceFileEdit {
869                                 file_id: FileId(
870                                     0,
871                                 ),
872                                 edit: TextEdit {
873                                     indels: [
874                                         Indel {
875                                             insert: "foo2",
876                                             delete: 4..7,
877                                         },
878                                     ],
879                                 },
880                             },
881                         ],
882                         file_system_edits: [
883                             MoveFile {
884                                 src: FileId(
885                                     1,
886                                 ),
887                                 anchor: FileId(
888                                     1,
889                                 ),
890                                 dst: "../foo2/mod.rs",
891                             },
892                         ],
893                         is_snippet: false,
894                     },
895                 }
896             "#]],
897         );
898     }
899
900     #[test]
901     fn test_rename_unusually_nested_mod() {
902         check_expect(
903             "bar",
904             r#"
905 //- /lib.rs
906 mod outer { mod fo<|>o; }
907
908 //- /outer/foo.rs
909 // emtpy
910 "#,
911             expect![[r#"
912                 RangeInfo {
913                     range: 16..19,
914                     info: SourceChange {
915                         source_file_edits: [
916                             SourceFileEdit {
917                                 file_id: FileId(
918                                     0,
919                                 ),
920                                 edit: TextEdit {
921                                     indels: [
922                                         Indel {
923                                             insert: "bar",
924                                             delete: 16..19,
925                                         },
926                                     ],
927                                 },
928                             },
929                         ],
930                         file_system_edits: [
931                             MoveFile {
932                                 src: FileId(
933                                     1,
934                                 ),
935                                 anchor: FileId(
936                                     1,
937                                 ),
938                                 dst: "bar.rs",
939                             },
940                         ],
941                         is_snippet: false,
942                     },
943                 }
944             "#]],
945         );
946     }
947
948     #[test]
949     fn test_module_rename_in_path() {
950         check(
951             "baz",
952             r#"
953 mod <|>foo { pub fn bar() {} }
954
955 fn main() { foo::bar(); }
956 "#,
957             r#"
958 mod baz { pub fn bar() {} }
959
960 fn main() { baz::bar(); }
961 "#,
962         );
963     }
964
965     #[test]
966     fn test_rename_mod_filename_and_path() {
967         check_expect(
968             "foo2",
969             r#"
970 //- /lib.rs
971 mod bar;
972 fn f() {
973     bar::foo::fun()
974 }
975
976 //- /bar.rs
977 pub mod foo<|>;
978
979 //- /bar/foo.rs
980 // pub fn fun() {}
981 "#,
982             expect![[r#"
983                 RangeInfo {
984                     range: 8..11,
985                     info: SourceChange {
986                         source_file_edits: [
987                             SourceFileEdit {
988                                 file_id: FileId(
989                                     1,
990                                 ),
991                                 edit: TextEdit {
992                                     indels: [
993                                         Indel {
994                                             insert: "foo2",
995                                             delete: 8..11,
996                                         },
997                                     ],
998                                 },
999                             },
1000                             SourceFileEdit {
1001                                 file_id: FileId(
1002                                     0,
1003                                 ),
1004                                 edit: TextEdit {
1005                                     indels: [
1006                                         Indel {
1007                                             insert: "foo2",
1008                                             delete: 27..30,
1009                                         },
1010                                     ],
1011                                 },
1012                             },
1013                         ],
1014                         file_system_edits: [
1015                             MoveFile {
1016                                 src: FileId(
1017                                     2,
1018                                 ),
1019                                 anchor: FileId(
1020                                     2,
1021                                 ),
1022                                 dst: "foo2.rs",
1023                             },
1024                         ],
1025                         is_snippet: false,
1026                     },
1027                 }
1028             "#]],
1029         );
1030     }
1031
1032     #[test]
1033     fn test_enum_variant_from_module_1() {
1034         check(
1035             "Baz",
1036             r#"
1037 mod foo {
1038     pub enum Foo { Bar<|> }
1039 }
1040
1041 fn func(f: foo::Foo) {
1042     match f {
1043         foo::Foo::Bar => {}
1044     }
1045 }
1046 "#,
1047             r#"
1048 mod foo {
1049     pub enum Foo { Baz }
1050 }
1051
1052 fn func(f: foo::Foo) {
1053     match f {
1054         foo::Foo::Baz => {}
1055     }
1056 }
1057 "#,
1058         );
1059     }
1060
1061     #[test]
1062     fn test_enum_variant_from_module_2() {
1063         check(
1064             "baz",
1065             r#"
1066 mod foo {
1067     pub struct Foo { pub bar<|>: uint }
1068 }
1069
1070 fn foo(f: foo::Foo) {
1071     let _ = f.bar;
1072 }
1073 "#,
1074             r#"
1075 mod foo {
1076     pub struct Foo { pub baz: uint }
1077 }
1078
1079 fn foo(f: foo::Foo) {
1080     let _ = f.baz;
1081 }
1082 "#,
1083         );
1084     }
1085
1086     #[test]
1087     fn test_parameter_to_self() {
1088         check(
1089             "self",
1090             r#"
1091 struct Foo { i: i32 }
1092
1093 impl Foo {
1094     fn f(foo<|>: &mut Foo) -> i32 {
1095         foo.i
1096     }
1097 }
1098 "#,
1099             r#"
1100 struct Foo { i: i32 }
1101
1102 impl Foo {
1103     fn f(&mut self) -> i32 {
1104         self.i
1105     }
1106 }
1107 "#,
1108         );
1109         check(
1110             "self",
1111             r#"
1112 struct Foo { i: i32 }
1113
1114 impl Foo {
1115     fn f(foo<|>: Foo) -> i32 {
1116         foo.i
1117     }
1118 }
1119 "#,
1120             r#"
1121 struct Foo { i: i32 }
1122
1123 impl Foo {
1124     fn f(self) -> i32 {
1125         self.i
1126     }
1127 }
1128 "#,
1129         );
1130     }
1131
1132     #[test]
1133     fn test_parameter_to_self_error_no_impl() {
1134         check(
1135             "self",
1136             r#"
1137 struct Foo { i: i32 }
1138
1139 fn f(foo<|>: &mut Foo) -> i32 {
1140     foo.i
1141 }
1142 "#,
1143             "error: No impl block found for function",
1144         );
1145         check(
1146             "self",
1147             r#"
1148 struct Foo { i: i32 }
1149 struct Bar;
1150
1151 impl Bar {
1152     fn f(foo<|>: &mut Foo) -> i32 {
1153         foo.i
1154     }
1155 }
1156 "#,
1157             "error: Parameter type differs from impl block type",
1158         );
1159     }
1160
1161     #[test]
1162     fn test_parameter_to_self_error_not_first() {
1163         check(
1164             "self",
1165             r#"
1166 struct Foo { i: i32 }
1167 impl Foo {
1168     fn f(x: (), foo<|>: &mut Foo) -> i32 {
1169         foo.i
1170     }
1171 }
1172 "#,
1173             "error: Only the first parameter can be self",
1174         );
1175     }
1176
1177     #[test]
1178     fn test_parameter_to_self_impl_ref() {
1179         check(
1180             "self",
1181             r#"
1182 struct Foo { i: i32 }
1183 impl &Foo {
1184     fn f(foo<|>: &Foo) -> i32 {
1185         foo.i
1186     }
1187 }
1188 "#,
1189             r#"
1190 struct Foo { i: i32 }
1191 impl &Foo {
1192     fn f(self) -> i32 {
1193         self.i
1194     }
1195 }
1196 "#,
1197         );
1198     }
1199
1200     #[test]
1201     fn test_self_to_parameter() {
1202         check(
1203             "foo",
1204             r#"
1205 struct Foo { i: i32 }
1206
1207 impl Foo {
1208     fn f(&mut <|>self) -> i32 {
1209         self.i
1210     }
1211 }
1212 "#,
1213             r#"
1214 struct Foo { i: i32 }
1215
1216 impl Foo {
1217     fn f(foo: &mut Foo) -> i32 {
1218         foo.i
1219     }
1220 }
1221 "#,
1222         );
1223     }
1224
1225     #[test]
1226     fn test_owned_self_to_parameter() {
1227         check(
1228             "foo",
1229             r#"
1230 struct Foo { i: i32 }
1231
1232 impl Foo {
1233     fn f(<|>self) -> i32 {
1234         self.i
1235     }
1236 }
1237 "#,
1238             r#"
1239 struct Foo { i: i32 }
1240
1241 impl Foo {
1242     fn f(foo: Foo) -> i32 {
1243         foo.i
1244     }
1245 }
1246 "#,
1247         );
1248     }
1249
1250     #[test]
1251     fn test_self_in_path_to_parameter() {
1252         check(
1253             "foo",
1254             r#"
1255 struct Foo { i: i32 }
1256
1257 impl Foo {
1258     fn f(&self) -> i32 {
1259         let self_var = 1;
1260         self<|>.i
1261     }
1262 }
1263 "#,
1264             r#"
1265 struct Foo { i: i32 }
1266
1267 impl Foo {
1268     fn f(foo: &Foo) -> i32 {
1269         let self_var = 1;
1270         foo.i
1271     }
1272 }
1273 "#,
1274         );
1275     }
1276
1277     #[test]
1278     fn test_initializer_use_field_init_shorthand() {
1279         mark::check!(test_rename_field_expr_pat);
1280         check(
1281             "bar",
1282             r#"
1283 struct Foo { i<|>: i32 }
1284
1285 fn foo(bar: i32) -> Foo {
1286     Foo { i: bar }
1287 }
1288 "#,
1289             r#"
1290 struct Foo { bar: i32 }
1291
1292 fn foo(bar: i32) -> Foo {
1293     Foo { bar }
1294 }
1295 "#,
1296         );
1297     }
1298
1299     #[test]
1300     fn test_struct_field_destructure_into_shorthand() {
1301         check(
1302             "baz",
1303             r#"
1304 struct Foo { i<|>: i32 }
1305
1306 fn foo(foo: Foo) {
1307     let Foo { i: baz } = foo;
1308     let _ = baz;
1309 }
1310 "#,
1311             r#"
1312 struct Foo { baz: i32 }
1313
1314 fn foo(foo: Foo) {
1315     let Foo { baz } = foo;
1316     let _ = baz;
1317 }
1318 "#,
1319         );
1320     }
1321
1322     #[test]
1323     fn test_rename_binding_in_destructure_pat() {
1324         let expected_fixture = r#"
1325 struct Foo {
1326     i: i32,
1327 }
1328
1329 fn foo(foo: Foo) {
1330     let Foo { i: bar } = foo;
1331     let _ = bar;
1332 }
1333 "#;
1334         check(
1335             "bar",
1336             r#"
1337 struct Foo {
1338     i: i32,
1339 }
1340
1341 fn foo(foo: Foo) {
1342     let Foo { i: b } = foo;
1343     let _ = b<|>;
1344 }
1345 "#,
1346             expected_fixture,
1347         );
1348         check(
1349             "bar",
1350             r#"
1351 struct Foo {
1352     i: i32,
1353 }
1354
1355 fn foo(foo: Foo) {
1356     let Foo { i } = foo;
1357     let _ = i<|>;
1358 }
1359 "#,
1360             expected_fixture,
1361         );
1362     }
1363
1364     #[test]
1365     fn test_rename_binding_in_destructure_param_pat() {
1366         check(
1367             "bar",
1368             r#"
1369 struct Foo {
1370     i: i32
1371 }
1372
1373 fn foo(Foo { i }: foo) -> i32 {
1374     i<|>
1375 }
1376 "#,
1377             r#"
1378 struct Foo {
1379     i: i32
1380 }
1381
1382 fn foo(Foo { i: bar }: foo) -> i32 {
1383     bar
1384 }
1385 "#,
1386         )
1387     }
1388 }