1 //! FIXME: write short doc here
7 use hir::{Module, ModuleDef, ModuleSource, Semantics};
9 base_db::{AnchoredPathBuf, FileId, FileRange, SourceDatabaseExt},
10 defs::{Definition, NameClass, NameRefClass},
11 search::FileReference,
15 algo::find_node_at_offset,
16 ast::{self, NameOwner},
17 lex_single_syntax_kind, match_ast, AstNode, SyntaxKind, SyntaxNode, SyntaxToken, T,
20 use text_edit::TextEdit;
23 FilePosition, FileSystemEdit, RangeInfo, ReferenceKind, ReferenceSearchResult, SourceChange,
27 type RenameResult<T> = Result<T, RenameError>;
29 pub struct RenameError(pub(crate) String);
31 impl fmt::Display for RenameError {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 Display::fmt(&self.0, f)
37 macro_rules! format_err {
38 ($fmt:expr) => {RenameError(format!($fmt))};
39 ($fmt:expr, $($arg:tt)+) => {RenameError(format!($fmt, $($arg)+))}
43 ($($tokens:tt)*) => {return Err(format_err!($($tokens)*))}
46 pub(crate) fn prepare_rename(
48 position: FilePosition,
49 ) -> RenameResult<RangeInfo<()>> {
50 let sema = Semantics::new(db);
51 let source_file = sema.parse(position.file_id);
52 let syntax = source_file.syntax();
53 if let Some(module) = find_module_at_offset(&sema, position, syntax) {
54 rename_mod(&sema, position, module, "dummy")
55 } else if let Some(self_token) =
56 syntax.token_at_offset(position.offset).find(|t| t.kind() == T![self])
58 rename_self_to_param(&sema, position, self_token, "dummy")
60 let RangeInfo { range, .. } = find_all_refs(&sema, position)?;
61 Ok(RangeInfo::new(range, SourceChange::default()))
63 .map(|info| RangeInfo::new(info.range, ()))
68 position: FilePosition,
70 ) -> RenameResult<RangeInfo<SourceChange>> {
71 let sema = Semantics::new(db);
72 rename_with_semantics(&sema, position, new_name)
75 pub(crate) fn rename_with_semantics(
76 sema: &Semantics<RootDatabase>,
77 position: FilePosition,
79 ) -> RenameResult<RangeInfo<SourceChange>> {
80 let source_file = sema.parse(position.file_id);
81 let syntax = source_file.syntax();
83 if let Some(module) = find_module_at_offset(&sema, position, syntax) {
84 rename_mod(&sema, position, module, new_name)
85 } else if let Some(self_token) =
86 syntax.token_at_offset(position.offset).find(|t| t.kind() == T![self])
88 rename_self_to_param(&sema, position, self_token, new_name)
90 rename_reference(&sema, position, new_name)
94 pub(crate) fn will_rename_file(
98 ) -> Option<SourceChange> {
99 let sema = Semantics::new(db);
100 let module = sema.to_module_def(file_id)?;
102 let decl = module.declaration_source(db)?;
103 let range = decl.value.name()?.syntax().text_range();
105 let position = FilePosition { file_id: decl.file_id.original_file(db), offset: range.start() };
106 let mut change = rename_mod(&sema, position, module, new_name_stem).ok()?.info;
107 change.file_system_edits.clear();
111 #[derive(Debug, PartialEq)]
112 enum IdentifierKind {
119 fn check_identifier(new_name: &str) -> RenameResult<IdentifierKind> {
120 match lex_single_syntax_kind(new_name) {
121 Some(res) => match res {
122 (SyntaxKind::IDENT, _) => Ok(IdentifierKind::Ident),
123 (T![_], _) => Ok(IdentifierKind::Underscore),
124 (T![self], _) => Ok(IdentifierKind::ToSelf),
125 (SyntaxKind::LIFETIME_IDENT, _) if new_name != "'static" && new_name != "'_" => {
126 Ok(IdentifierKind::Lifetime)
128 (SyntaxKind::LIFETIME_IDENT, _) => {
129 bail!("Invalid name `{0}`: Cannot rename lifetime to {0}", new_name)
131 (_, Some(syntax_error)) => bail!("Invalid name `{}`: {}", new_name, syntax_error),
132 (_, None) => bail!("Invalid name `{}`: not an identifier", new_name),
134 None => bail!("Invalid name `{}`: not an identifier", new_name),
138 fn find_module_at_offset(
139 sema: &Semantics<RootDatabase>,
140 position: FilePosition,
142 ) -> Option<Module> {
143 let ident = syntax.token_at_offset(position.offset).find(|t| t.kind() == SyntaxKind::IDENT)?;
145 let module = match_ast! {
146 match (ident.parent()) {
147 ast::NameRef(name_ref) => {
148 match NameRefClass::classify(sema, &name_ref)? {
149 NameRefClass::Definition(Definition::ModuleDef(ModuleDef::Module(module))) => module,
154 match NameClass::classify(&sema, &name)? {
155 NameClass::Definition(Definition::ModuleDef(ModuleDef::Module(module))) => module,
167 sema: &Semantics<RootDatabase>,
168 position: FilePosition,
169 ) -> RenameResult<RangeInfo<ReferenceSearchResult>> {
170 crate::references::find_all_refs(sema, position, None)
171 .ok_or_else(|| format_err!("No references found at position"))
174 fn source_edit_from_references(
175 sema: &Semantics<RootDatabase>,
177 references: &[FileReference],
179 ) -> (FileId, TextEdit) {
180 let mut edit = TextEdit::builder();
181 for reference in references {
182 let mut replacement_text = String::new();
183 let range = match reference.kind {
184 ReferenceKind::FieldShorthandForField => {
185 mark::hit!(test_rename_struct_field_for_shorthand);
186 replacement_text.push_str(new_name);
187 replacement_text.push_str(": ");
188 TextRange::new(reference.range.start(), reference.range.start())
190 ReferenceKind::FieldShorthandForLocal => {
191 mark::hit!(test_rename_local_for_field_shorthand);
192 replacement_text.push_str(": ");
193 replacement_text.push_str(new_name);
194 TextRange::new(reference.range.end(), reference.range.end())
196 ReferenceKind::RecordFieldExprOrPat => {
197 mark::hit!(test_rename_field_expr_pat);
198 replacement_text.push_str(new_name);
199 edit_text_range_for_record_field_expr_or_pat(
201 FileRange { file_id, range: reference.range },
206 replacement_text.push_str(new_name);
210 edit.replace(range, replacement_text);
212 (file_id, edit.finish())
215 fn edit_text_range_for_record_field_expr_or_pat(
216 sema: &Semantics<RootDatabase>,
217 file_range: FileRange,
220 let source_file = sema.parse(file_range.file_id);
221 let file_syntax = source_file.syntax();
222 let original_range = file_range.range;
224 syntax::algo::find_node_at_range::<ast::RecordExprField>(file_syntax, original_range)
225 .and_then(|field_expr| match field_expr.expr().and_then(|e| e.name_ref()) {
226 Some(name) if &name.to_string() == new_name => Some(field_expr.syntax().text_range()),
230 syntax::algo::find_node_at_range::<ast::RecordPatField>(file_syntax, original_range)
231 .and_then(|field_pat| match field_pat.pat() {
232 Some(ast::Pat::IdentPat(pat))
233 if pat.name().map(|n| n.to_string()).as_deref() == Some(new_name) =>
235 Some(field_pat.syntax().text_range())
240 .unwrap_or(original_range)
244 sema: &Semantics<RootDatabase>,
245 position: FilePosition,
248 ) -> RenameResult<RangeInfo<SourceChange>> {
249 if IdentifierKind::Ident != check_identifier(new_name)? {
250 bail!("Invalid name `{0}`: cannot rename module to {0}", new_name);
253 let mut source_change = SourceChange::default();
255 let src = module.definition_source(sema.db);
256 let file_id = src.file_id.original_file(sema.db);
258 ModuleSource::SourceFile(..) => {
259 // mod is defined in path/to/dir/mod.rs
260 let path = if module.is_mod_rs(sema.db) {
261 format!("../{}/mod.rs", new_name)
263 format!("{}.rs", new_name)
265 let dst = AnchoredPathBuf { anchor: file_id, path };
266 let move_file = FileSystemEdit::MoveFile { src: file_id, dst };
267 source_change.push_file_system_edit(move_file);
269 ModuleSource::Module(..) => {}
272 if let Some(src) = module.declaration_source(sema.db) {
273 let file_id = src.file_id.original_file(sema.db);
274 let name = src.value.name().unwrap();
275 source_change.insert_source_edit(
277 TextEdit::replace(name.syntax().text_range(), new_name.into()),
281 let RangeInfo { range, info: refs } = find_all_refs(sema, position)?;
282 let ref_edits = refs.references().iter().map(|(&file_id, references)| {
283 source_edit_from_references(sema, file_id, references, new_name)
285 source_change.extend(ref_edits);
287 Ok(RangeInfo::new(range, source_change))
291 sema: &Semantics<RootDatabase>,
292 position: FilePosition,
293 ) -> Result<RangeInfo<SourceChange>, RenameError> {
294 let source_file = sema.parse(position.file_id);
295 let syn = source_file.syntax();
297 let (fn_def, fn_ast) = find_node_at_offset::<ast::Fn>(syn, position.offset)
298 .and_then(|fn_ast| sema.to_def(&fn_ast).zip(Some(fn_ast)))
299 .ok_or_else(|| format_err!("No surrounding method declaration found"))?;
300 let param_range = fn_ast
302 .and_then(|p| p.params().next())
303 .ok_or_else(|| format_err!("Method has no parameters"))?
306 if !param_range.contains(position.offset) {
307 bail!("Only the first parameter can be self");
310 let impl_block = find_node_at_offset::<ast::Impl>(syn, position.offset)
311 .and_then(|def| sema.to_def(&def))
312 .ok_or_else(|| format_err!("No impl block found for function"))?;
313 if fn_def.self_param(sema.db).is_some() {
314 bail!("Method already has a self parameter");
317 let params = fn_def.assoc_fn_params(sema.db);
318 let first_param = params.first().ok_or_else(|| format_err!("Method has no parameters"))?;
319 let first_param_ty = first_param.ty();
320 let impl_ty = impl_block.target_ty(sema.db);
321 let (ty, self_param) = if impl_ty.remove_ref().is_some() {
322 // if the impl is a ref to the type we can just match the `&T` with self directly
323 (first_param_ty.clone(), "self")
325 first_param_ty.remove_ref().map_or((first_param_ty.clone(), "self"), |ty| {
326 (ty, if first_param_ty.is_mutable_reference() { "&mut self" } else { "&self" })
331 bail!("Parameter type differs from impl block type");
334 let RangeInfo { range, info: refs } = find_all_refs(sema, position)?;
336 let mut source_change = SourceChange::default();
337 source_change.extend(refs.references().iter().map(|(&file_id, references)| {
338 source_edit_from_references(sema, file_id, references, "self")
340 source_change.insert_source_edit(
342 TextEdit::replace(param_range, String::from(self_param)),
345 Ok(RangeInfo::new(range, source_change))
348 fn text_edit_from_self_param(
350 self_param: &ast::SelfParam,
352 ) -> Option<TextEdit> {
353 fn target_type_name(impl_def: &ast::Impl) -> Option<String> {
354 if let Some(ast::Type::PathType(p)) = impl_def.self_ty() {
355 return Some(p.path()?.segment()?.name_ref()?.text().to_string());
360 let impl_def = find_node_at_offset::<ast::Impl>(syn, self_param.syntax().text_range().start())?;
361 let type_name = target_type_name(&impl_def)?;
363 let mut replacement_text = String::from(new_name);
364 replacement_text.push_str(": ");
365 match (self_param.amp_token(), self_param.mut_token()) {
367 (Some(_), None) => replacement_text.push('&'),
368 (_, Some(_)) => replacement_text.push_str("&mut "),
370 replacement_text.push_str(type_name.as_str());
372 Some(TextEdit::replace(self_param.syntax().text_range(), replacement_text))
375 fn rename_self_to_param(
376 sema: &Semantics<RootDatabase>,
377 position: FilePosition,
378 self_token: SyntaxToken,
380 ) -> Result<RangeInfo<SourceChange>, RenameError> {
381 let ident_kind = check_identifier(new_name)?;
383 IdentifierKind::Lifetime => bail!("Invalid name `{}`: not an identifier", new_name),
384 IdentifierKind::ToSelf => {
386 mark::hit!(rename_self_to_self);
387 return Ok(RangeInfo::new(self_token.text_range(), SourceChange::default()));
391 let source_file = sema.parse(position.file_id);
392 let syn = source_file.syntax();
394 let text = sema.db.file_text(position.file_id);
395 let fn_def = find_node_at_offset::<ast::Fn>(syn, position.offset)
396 .ok_or_else(|| format_err!("No surrounding method declaration found"))?;
397 let search_range = fn_def.syntax().text_range();
399 let mut source_change = SourceChange::default();
401 for (idx, _) in text.match_indices("self") {
402 let offset: TextSize = idx.try_into().unwrap();
403 if !search_range.contains_inclusive(offset) {
406 if let Some(ref usage) = syn.token_at_offset(offset).find(|t| t.kind() == T![self]) {
407 let edit = if let Some(ref self_param) = ast::SelfParam::cast(usage.parent()) {
408 text_edit_from_self_param(syn, self_param, new_name)
409 .ok_or_else(|| format_err!("No target type found"))?
411 TextEdit::replace(usage.text_range(), String::from(new_name))
413 source_change.insert_source_edit(position.file_id, edit);
417 if source_change.source_file_edits.len() > 1 && ident_kind == IdentifierKind::Underscore {
418 bail!("Cannot rename reference to `_` as it is being referenced multiple times");
421 let range = ast::SelfParam::cast(self_token.parent())
422 .map_or(self_token.text_range(), |p| p.syntax().text_range());
424 Ok(RangeInfo::new(range, source_change))
428 sema: &Semantics<RootDatabase>,
429 position: FilePosition,
431 ) -> Result<RangeInfo<SourceChange>, RenameError> {
432 let ident_kind = check_identifier(new_name)?;
433 let RangeInfo { range, info: refs } = find_all_refs(sema, position)?;
435 match (ident_kind, &refs.declaration.kind) {
436 (IdentifierKind::ToSelf, ReferenceKind::Lifetime)
437 | (IdentifierKind::Underscore, ReferenceKind::Lifetime)
438 | (IdentifierKind::Ident, ReferenceKind::Lifetime) => {
439 mark::hit!(rename_not_a_lifetime_ident_ref);
440 bail!("Invalid name `{}`: not a lifetime identifier", new_name)
442 (IdentifierKind::Lifetime, ReferenceKind::Lifetime) => mark::hit!(rename_lifetime),
443 (IdentifierKind::Lifetime, _) => {
444 mark::hit!(rename_not_an_ident_ref);
445 bail!("Invalid name `{}`: not an identifier", new_name)
447 (IdentifierKind::ToSelf, ReferenceKind::SelfKw) => {
448 unreachable!("rename_self_to_param should've been called instead")
450 (IdentifierKind::ToSelf, _) => {
451 mark::hit!(rename_to_self);
452 return rename_to_self(sema, position);
454 (IdentifierKind::Underscore, _) if !refs.references.is_empty() => {
455 mark::hit!(rename_underscore_multiple);
456 bail!("Cannot rename reference to `_` as it is being referenced multiple times")
458 (IdentifierKind::Ident, _) | (IdentifierKind::Underscore, _) => mark::hit!(rename_ident),
461 let mut source_change = SourceChange::default();
462 source_change.extend(refs.into_iter().map(|(file_id, references)| {
463 source_edit_from_references(sema, file_id, &references, new_name)
466 Ok(RangeInfo::new(range, source_change))
471 use expect_test::{expect, Expect};
472 use stdx::trim_indent;
473 use test_utils::{assert_eq_text, mark};
474 use text_edit::TextEdit;
476 use crate::{fixture, FileId};
478 fn check(new_name: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
479 let ra_fixture_after = &trim_indent(ra_fixture_after);
480 let (analysis, position) = fixture::position(ra_fixture_before);
481 let rename_result = analysis
482 .rename(position, new_name)
483 .unwrap_or_else(|err| panic!("Rename to '{}' was cancelled: {}", new_name, err));
484 match rename_result {
485 Ok(source_change) => {
486 let mut text_edit_builder = TextEdit::builder();
487 let mut file_id: Option<FileId> = None;
488 for edit in source_change.info.source_file_edits {
489 file_id = Some(edit.0);
490 for indel in edit.1.into_iter() {
491 text_edit_builder.replace(indel.delete, indel.insert);
494 if let Some(file_id) = file_id {
495 let mut result = analysis.file_text(file_id).unwrap().to_string();
496 text_edit_builder.finish().apply(&mut result);
497 assert_eq_text!(ra_fixture_after, &*result);
501 if ra_fixture_after.starts_with("error:") {
502 let error_message = ra_fixture_after
505 .skip("error:".len())
506 .collect::<String>();
507 assert_eq!(error_message.trim(), err.to_string());
510 panic!("Rename to '{}' failed unexpectedly: {}", new_name, err)
516 fn check_expect(new_name: &str, ra_fixture: &str, expect: Expect) {
517 let (analysis, position) = fixture::position(ra_fixture);
518 let source_change = analysis
519 .rename(position, new_name)
521 .expect("Expect returned RangeInfo to be Some, but was None");
522 expect.assert_debug_eq(&source_change)
526 fn test_rename_to_underscore() {
527 check("_", r#"fn main() { let i$0 = 1; }"#, r#"fn main() { let _ = 1; }"#);
531 fn test_rename_to_raw_identifier() {
532 check("r#fn", r#"fn main() { let i$0 = 1; }"#, r#"fn main() { let r#fn = 1; }"#);
536 fn test_rename_to_invalid_identifier1() {
539 r#"fn main() { let i$0 = 1; }"#,
540 "error: Invalid name `invalid!`: not an identifier",
545 fn test_rename_to_invalid_identifier2() {
548 r#"fn main() { let i$0 = 1; }"#,
549 "error: Invalid name `multiple tokens`: not an identifier",
554 fn test_rename_to_invalid_identifier3() {
557 r#"fn main() { let i$0 = 1; }"#,
558 "error: Invalid name `let`: not an identifier",
563 fn test_rename_to_invalid_identifier_lifetime() {
564 mark::check!(rename_not_an_ident_ref);
567 r#"fn main() { let i$0 = 1; }"#,
568 "error: Invalid name `'foo`: not an identifier",
573 fn test_rename_to_invalid_identifier_lifetime2() {
574 mark::check!(rename_not_a_lifetime_ident_ref);
577 r#"fn main<'a>(_: &'a$0 ()) {}"#,
578 "error: Invalid name `foo`: not a lifetime identifier",
583 fn test_rename_to_underscore_invalid() {
584 mark::check!(rename_underscore_multiple);
587 r#"fn main(foo$0: ()) {foo;}"#,
588 "error: Cannot rename reference to `_` as it is being referenced multiple times",
593 fn test_rename_mod_invalid() {
597 "error: Invalid name `'foo`: cannot rename module to 'foo",
602 fn test_rename_for_local() {
603 mark::check!(rename_ident);
632 fn test_rename_unresolved_reference() {
635 r#"fn main() { let _ = unresolved_ref$0; }"#,
636 "error: No references found at position",
641 fn test_rename_for_macro_args() {
645 macro_rules! foo {($i:ident) => {$i} }
652 macro_rules! foo {($i:ident) => {$i} }
662 fn test_rename_for_macro_args_rev() {
666 macro_rules! foo {($i:ident) => {$i} }
673 macro_rules! foo {($i:ident) => {$i} }
683 fn test_rename_for_macro_define_fn() {
687 macro_rules! define_fn {($id:ident) => { fn $id{} }}
694 macro_rules! define_fn {($id:ident) => { fn $id{} }}
704 fn test_rename_for_macro_define_fn_rev() {
708 macro_rules! define_fn {($id:ident) => { fn $id{} }}
715 macro_rules! define_fn {($id:ident) => { fn $id{} }}
725 fn test_rename_for_param_inside() {
726 check("j", r#"fn foo(i : u32) -> u32 { i$0 }"#, r#"fn foo(j : u32) -> u32 { j }"#);
730 fn test_rename_refs_for_fn_param() {
731 check("j", r#"fn foo(i$0 : u32) -> u32 { i }"#, r#"fn foo(j : u32) -> u32 { j }"#);
735 fn test_rename_for_mut_param() {
736 check("j", r#"fn foo(mut i$0 : u32) -> u32 { i }"#, r#"fn foo(mut j : u32) -> u32 { j }"#);
740 fn test_rename_struct_field() {
744 struct Foo { i$0: i32 }
747 fn new(i: i32) -> Self {
753 struct Foo { j: i32 }
756 fn new(i: i32) -> Self {
765 fn test_rename_struct_field_for_shorthand() {
766 mark::check!(test_rename_struct_field_for_shorthand);
770 struct Foo { i$0: i32 }
773 fn new(i: i32) -> Self {
779 struct Foo { j: i32 }
782 fn new(i: i32) -> Self {
791 fn test_rename_local_for_field_shorthand() {
792 mark::check!(test_rename_local_for_field_shorthand);
796 struct Foo { i: i32 }
799 fn new(i$0: i32) -> Self {
805 struct Foo { i: i32 }
808 fn new(j: i32) -> Self {
817 fn test_field_shorthand_correct_struct() {
821 struct Foo { i$0: i32 }
822 struct Bar { i: i32 }
825 fn new(i: i32) -> Self {
831 struct Foo { j: i32 }
832 struct Bar { i: i32 }
835 fn new(i: i32) -> Self {
844 fn test_shadow_local_for_struct_shorthand() {
848 struct Foo { i: i32 }
850 fn baz(i$0: i32) -> Self {
859 struct Foo { i: i32 }
861 fn baz(j: i32) -> Self {
862 let x = Foo { i: j };
873 fn test_rename_mod() {
907 dst: AnchoredPathBuf {
923 fn test_rename_mod_in_use_tree() {
933 pub struct FooContent;
936 use crate::foo$0::FooContent;
969 dst: AnchoredPathBuf {
985 fn test_rename_mod_in_dir() {
1010 file_system_edits: [
1015 dst: AnchoredPathBuf {
1019 path: "../foo2/mod.rs",
1031 fn test_rename_unusually_nested_mod() {
1036 mod outer { mod fo$0o; }
1044 info: SourceChange {
1045 source_file_edits: {
1057 file_system_edits: [
1062 dst: AnchoredPathBuf {
1078 fn test_module_rename_in_path() {
1082 mod $0foo { pub fn bar() {} }
1084 fn main() { foo::bar(); }
1087 mod baz { pub fn bar() {} }
1089 fn main() { baz::bar(); }
1095 fn test_rename_mod_filename_and_path() {
1114 info: SourceChange {
1115 source_file_edits: {
1137 file_system_edits: [
1142 dst: AnchoredPathBuf {
1158 fn test_enum_variant_from_module_1() {
1163 pub enum Foo { Bar$0 }
1166 fn func(f: foo::Foo) {
1174 pub enum Foo { Baz }
1177 fn func(f: foo::Foo) {
1187 fn test_enum_variant_from_module_2() {
1192 pub struct Foo { pub bar$0: uint }
1195 fn foo(f: foo::Foo) {
1201 pub struct Foo { pub baz: uint }
1204 fn foo(f: foo::Foo) {
1212 fn test_parameter_to_self() {
1213 mark::check!(rename_to_self);
1217 struct Foo { i: i32 }
1220 fn f(foo$0: &mut Foo) -> i32 {
1226 struct Foo { i: i32 }
1229 fn f(&mut self) -> i32 {
1238 struct Foo { i: i32 }
1241 fn f(foo$0: Foo) -> i32 {
1247 struct Foo { i: i32 }
1259 fn test_parameter_to_self_error_no_impl() {
1263 struct Foo { i: i32 }
1265 fn f(foo$0: &mut Foo) -> i32 {
1269 "error: No impl block found for function",
1274 struct Foo { i: i32 }
1278 fn f(foo$0: &mut Foo) -> i32 {
1283 "error: Parameter type differs from impl block type",
1288 fn test_parameter_to_self_error_not_first() {
1292 struct Foo { i: i32 }
1294 fn f(x: (), foo$0: &mut Foo) -> i32 {
1299 "error: Only the first parameter can be self",
1304 fn test_parameter_to_self_impl_ref() {
1308 struct Foo { i: i32 }
1310 fn f(foo$0: &Foo) -> i32 {
1316 struct Foo { i: i32 }
1327 fn test_self_to_parameter() {
1331 struct Foo { i: i32 }
1334 fn f(&mut $0self) -> i32 {
1340 struct Foo { i: i32 }
1343 fn f(foo: &mut Foo) -> i32 {
1352 fn test_owned_self_to_parameter() {
1356 struct Foo { i: i32 }
1359 fn f($0self) -> i32 {
1365 struct Foo { i: i32 }
1368 fn f(foo: Foo) -> i32 {
1377 fn test_self_in_path_to_parameter() {
1381 struct Foo { i: i32 }
1384 fn f(&self) -> i32 {
1391 struct Foo { i: i32 }
1394 fn f(foo: &Foo) -> i32 {
1404 fn test_initializer_use_field_init_shorthand() {
1405 mark::check!(test_rename_field_expr_pat);
1409 struct Foo { i$0: i32 }
1411 fn foo(bar: i32) -> Foo {
1416 struct Foo { bar: i32 }
1418 fn foo(bar: i32) -> Foo {
1426 fn test_struct_field_destructure_into_shorthand() {
1430 struct Foo { i$0: i32 }
1433 let Foo { i: baz } = foo;
1438 struct Foo { baz: i32 }
1441 let Foo { baz } = foo;
1449 fn test_rename_binding_in_destructure_pat() {
1450 let expected_fixture = r#"
1456 let Foo { i: bar } = foo;
1468 let Foo { i: b } = foo;
1482 let Foo { i } = foo;
1491 fn test_rename_binding_in_destructure_param_pat() {
1499 fn foo(Foo { i }: foo) -> i32 {
1508 fn foo(Foo { i: bar }: foo) -> i32 {
1516 fn test_rename_lifetimes() {
1517 mark::check!(rename_lifetime);
1524 impl<'a> Foo<'a> for &'a () {
1525 fn foo() -> &'a$0 () {
1534 impl<'yeeee> Foo<'yeeee> for &'yeeee () {
1535 fn foo() -> &'yeeee () {
1544 fn test_rename_bind_pat() {
1549 enum CustomOption<T> {
1554 let test_variable = CustomOption::Some(22);
1556 match test_variable {
1557 CustomOption::Some(foo$0) if foo == 11 => {}
1563 enum CustomOption<T> {
1568 let test_variable = CustomOption::Some(22);
1570 match test_variable {
1571 CustomOption::Some(new_name) if new_name == 11 => {}
1579 fn test_rename_label() {
1583 fn foo<'a>() -> &'a () {
1592 fn foo<'a>() -> &'a () {
1604 fn test_self_to_self() {
1605 mark::check!(rename_self_to_self);