From da534bdd074788e47b5dae76998b8f8535ea7257 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 14 Jun 2021 19:14:34 +0300 Subject: internal: flatten module hierarchy It seems that any crate can be made better by flattening the modules down to a single layer? --- crates/ide/src/references/rename.rs | 1788 ----------------------------------- 1 file changed, 1788 deletions(-) delete mode 100644 crates/ide/src/references/rename.rs (limited to 'crates/ide/src/references') diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs deleted file mode 100644 index cec1d4552..000000000 --- a/crates/ide/src/references/rename.rs +++ /dev/null @@ -1,1788 +0,0 @@ -//! Renaming functionality -//! -//! All reference and file rename requests go through here where the corresponding [`SourceChange`]s -//! will be calculated. -use hir::{AsAssocItem, InFile, Semantics}; -use ide_db::{ - base_db::FileId, - defs::{Definition, NameClass, NameRefClass}, - rename::{bail, format_err, source_edit_from_references, IdentifierKind}, - RootDatabase, -}; -use stdx::never; -use syntax::{ast, AstNode, SyntaxNode}; - -use text_edit::TextEdit; - -use crate::{FilePosition, RangeInfo, SourceChange}; - -pub use ide_db::rename::RenameError; - -type RenameResult = Result; - -/// Prepares a rename. The sole job of this function is to return the TextRange of the thing that is -/// being targeted for a rename. -pub(crate) fn prepare_rename( - db: &RootDatabase, - position: FilePosition, -) -> RenameResult> { - let sema = Semantics::new(db); - let source_file = sema.parse(position.file_id); - let syntax = source_file.syntax(); - - let def = find_definition(&sema, syntax, position)?; - let frange = - def.rename_range(&sema).ok_or_else(|| format_err!("No references found at position"))?; - Ok(RangeInfo::new(frange.range, ())) -} - -// Feature: Rename -// -// Renames the item below the cursor and all of its references -// -// |=== -// | Editor | Shortcut -// -// | VS Code | kbd:[F2] -// |=== -// -// image::https://user-images.githubusercontent.com/48062697/113065582-055aae80-91b1-11eb-8ade-2b58e6d81883.gif[] -pub(crate) fn rename( - db: &RootDatabase, - position: FilePosition, - new_name: &str, -) -> RenameResult { - let sema = Semantics::new(db); - rename_with_semantics(&sema, position, new_name) -} - -pub(crate) fn rename_with_semantics( - sema: &Semantics, - position: FilePosition, - new_name: &str, -) -> RenameResult { - let source_file = sema.parse(position.file_id); - let syntax = source_file.syntax(); - - let def = find_definition(sema, syntax, position)?; - - if let Definition::Local(local) = def { - if let Some(self_param) = local.as_self_param(sema.db) { - cov_mark::hit!(rename_self_to_param); - return rename_self_to_param(sema, local, self_param, new_name); - } - if new_name == "self" { - cov_mark::hit!(rename_to_self); - return rename_to_self(sema, local); - } - } - - def.rename(sema, new_name) -} - -/// Called by the client when it is about to rename a file. -pub(crate) fn will_rename_file( - db: &RootDatabase, - file_id: FileId, - new_name_stem: &str, -) -> Option { - let sema = Semantics::new(db); - let module = sema.to_module_def(file_id)?; - let def = Definition::ModuleDef(module.into()); - let mut change = def.rename(&sema, new_name_stem).ok()?; - change.file_system_edits.clear(); - Some(change) -} - -fn find_definition( - sema: &Semantics, - syntax: &SyntaxNode, - position: FilePosition, -) -> RenameResult { - match sema - .find_node_at_offset_with_descend(syntax, position.offset) - .ok_or_else(|| format_err!("No references found at position"))? - { - // renaming aliases would rename the item being aliased as the HIR doesn't track aliases yet - ast::NameLike::Name(name) - if name.syntax().parent().map_or(false, |it| ast::Rename::can_cast(it.kind())) => - { - bail!("Renaming aliases is currently unsupported") - } - ast::NameLike::Name(name) => { - NameClass::classify(sema, &name).map(|class| class.referenced_or_defined(sema.db)) - } - ast::NameLike::NameRef(name_ref) => { - if let Some(def) = - NameRefClass::classify(sema, &name_ref).map(|class| class.referenced(sema.db)) - { - // if the name differs from the definitions name it has to be an alias - if def.name(sema.db).map_or(false, |it| it.to_string() != name_ref.text()) { - bail!("Renaming aliases is currently unsupported"); - } - Some(def) - } else { - None - } - } - ast::NameLike::Lifetime(lifetime) => NameRefClass::classify_lifetime(sema, &lifetime) - .map(|class| NameRefClass::referenced(class, sema.db)) - .or_else(|| { - NameClass::classify_lifetime(sema, &lifetime) - .map(|it| it.referenced_or_defined(sema.db)) - }), - } - .ok_or_else(|| format_err!("No references found at position")) -} - -fn rename_to_self(sema: &Semantics, local: hir::Local) -> RenameResult { - if never!(local.is_self(sema.db)) { - bail!("rename_to_self invoked on self"); - } - - let fn_def = match local.parent(sema.db) { - hir::DefWithBody::Function(func) => func, - _ => bail!("Cannot rename local to self outside of function"), - }; - - if let Some(_) = fn_def.self_param(sema.db) { - bail!("Method already has a self parameter"); - } - - let params = fn_def.assoc_fn_params(sema.db); - let first_param = params - .first() - .ok_or_else(|| format_err!("Cannot rename local to self unless it is a parameter"))?; - if first_param.as_local(sema.db) != local { - bail!("Only the first parameter may be renamed to self"); - } - - let assoc_item = fn_def - .as_assoc_item(sema.db) - .ok_or_else(|| format_err!("Cannot rename parameter to self for free function"))?; - let impl_ = match assoc_item.container(sema.db) { - hir::AssocItemContainer::Trait(_) => { - bail!("Cannot rename parameter to self for trait functions"); - } - hir::AssocItemContainer::Impl(impl_) => impl_, - }; - let first_param_ty = first_param.ty(); - let impl_ty = impl_.self_ty(sema.db); - let (ty, self_param) = if impl_ty.remove_ref().is_some() { - // if the impl is a ref to the type we can just match the `&T` with self directly - (first_param_ty.clone(), "self") - } else { - first_param_ty.remove_ref().map_or((first_param_ty.clone(), "self"), |ty| { - (ty, if first_param_ty.is_mutable_reference() { "&mut self" } else { "&self" }) - }) - }; - - if ty != impl_ty { - bail!("Parameter type differs from impl block type"); - } - - let InFile { file_id, value: param_source } = - first_param.source(sema.db).ok_or_else(|| format_err!("No source for parameter found"))?; - - let def = Definition::Local(local); - let usages = def.usages(sema).all(); - let mut source_change = SourceChange::default(); - source_change.extend(usages.iter().map(|(&file_id, references)| { - (file_id, source_edit_from_references(references, def, "self")) - })); - source_change.insert_source_edit( - file_id.original_file(sema.db), - TextEdit::replace(param_source.syntax().text_range(), String::from(self_param)), - ); - Ok(source_change) -} - -fn rename_self_to_param( - sema: &Semantics, - local: hir::Local, - self_param: hir::SelfParam, - new_name: &str, -) -> RenameResult { - if new_name == "self" { - // Let's do nothing rather than complain. - cov_mark::hit!(rename_self_to_self); - return Ok(SourceChange::default()); - } - - let identifier_kind = IdentifierKind::classify(new_name)?; - - let InFile { file_id, value: self_param } = - self_param.source(sema.db).ok_or_else(|| format_err!("cannot find function source"))?; - - let def = Definition::Local(local); - let usages = def.usages(sema).all(); - let edit = text_edit_from_self_param(&self_param, new_name) - .ok_or_else(|| format_err!("No target type found"))?; - if usages.len() > 1 && identifier_kind == IdentifierKind::Underscore { - bail!("Cannot rename reference to `_` as it is being referenced multiple times"); - } - let mut source_change = SourceChange::default(); - source_change.insert_source_edit(file_id.original_file(sema.db), edit); - source_change.extend(usages.iter().map(|(&file_id, references)| { - (file_id, source_edit_from_references(references, def, new_name)) - })); - Ok(source_change) -} - -fn text_edit_from_self_param(self_param: &ast::SelfParam, new_name: &str) -> Option { - fn target_type_name(impl_def: &ast::Impl) -> Option { - if let Some(ast::Type::PathType(p)) = impl_def.self_ty() { - return Some(p.path()?.segment()?.name_ref()?.text().to_string()); - } - None - } - - let impl_def = self_param.syntax().ancestors().find_map(ast::Impl::cast)?; - let type_name = target_type_name(&impl_def)?; - - let mut replacement_text = String::from(new_name); - replacement_text.push_str(": "); - match (self_param.amp_token(), self_param.mut_token()) { - (Some(_), None) => replacement_text.push('&'), - (Some(_), Some(_)) => replacement_text.push_str("&mut "), - (_, _) => (), - }; - replacement_text.push_str(type_name.as_str()); - - Some(TextEdit::replace(self_param.syntax().text_range(), replacement_text)) -} - -#[cfg(test)] -mod tests { - use expect_test::{expect, Expect}; - use stdx::trim_indent; - use test_utils::assert_eq_text; - use text_edit::TextEdit; - - use crate::{fixture, FileId}; - - use super::{RangeInfo, RenameError}; - - fn check(new_name: &str, ra_fixture_before: &str, ra_fixture_after: &str) { - let ra_fixture_after = &trim_indent(ra_fixture_after); - let (analysis, position) = fixture::position(ra_fixture_before); - let rename_result = analysis - .rename(position, new_name) - .unwrap_or_else(|err| panic!("Rename to '{}' was cancelled: {}", new_name, err)); - match rename_result { - Ok(source_change) => { - let mut text_edit_builder = TextEdit::builder(); - let mut file_id: Option = None; - for edit in source_change.source_file_edits { - file_id = Some(edit.0); - for indel in edit.1.into_iter() { - text_edit_builder.replace(indel.delete, indel.insert); - } - } - if let Some(file_id) = file_id { - let mut result = analysis.file_text(file_id).unwrap().to_string(); - text_edit_builder.finish().apply(&mut result); - assert_eq_text!(ra_fixture_after, &*result); - } - } - Err(err) => { - if ra_fixture_after.starts_with("error:") { - let error_message = ra_fixture_after - .chars() - .into_iter() - .skip("error:".len()) - .collect::(); - assert_eq!(error_message.trim(), err.to_string()); - return; - } else { - panic!("Rename to '{}' failed unexpectedly: {}", new_name, err) - } - } - }; - } - - fn check_expect(new_name: &str, ra_fixture: &str, expect: Expect) { - let (analysis, position) = fixture::position(ra_fixture); - let source_change = - analysis.rename(position, new_name).unwrap().expect("Expect returned a RenameError"); - expect.assert_debug_eq(&source_change) - } - - fn check_prepare(ra_fixture: &str, expect: Expect) { - let (analysis, position) = fixture::position(ra_fixture); - let result = analysis - .prepare_rename(position) - .unwrap_or_else(|err| panic!("PrepareRename was cancelled: {}", err)); - match result { - Ok(RangeInfo { range, info: () }) => { - let source = analysis.file_text(position.file_id).unwrap(); - expect.assert_eq(&format!("{:?}: {}", range, &source[range])) - } - Err(RenameError(err)) => expect.assert_eq(&err), - }; - } - - #[test] - fn test_prepare_rename_namelikes() { - check_prepare(r"fn name$0<'lifetime>() {}", expect![[r#"3..7: name"#]]); - check_prepare(r"fn name<'lifetime$0>() {}", expect![[r#"8..17: 'lifetime"#]]); - check_prepare(r"fn name<'lifetime>() { name$0(); }", expect![[r#"3..7: name"#]]); - } - - #[test] - fn test_prepare_rename_in_macro() { - check_prepare( - r"macro_rules! foo { - ($ident:ident) => { - pub struct $ident; - } -} -foo!(Foo$0);", - expect![[r#"83..86: Foo"#]], - ); - } - - #[test] - fn test_prepare_rename_keyword() { - check_prepare(r"struct$0 Foo;", expect![[r#"No references found at position"#]]); - } - - #[test] - fn test_prepare_rename_tuple_field() { - check_prepare( - r#" -struct Foo(i32); - -fn baz() { - let mut x = Foo(4); - x.0$0 = 5; -} -"#, - expect![[r#"No references found at position"#]], - ); - } - - #[test] - fn test_prepare_rename_builtin() { - check_prepare( - r#" -fn foo() { - let x: i32$0 = 0; -} -"#, - expect![[r#"No references found at position"#]], - ); - } - - #[test] - fn test_prepare_rename_self() { - check_prepare( - r#" -struct Foo {} - -impl Foo { - fn foo(self) -> Self$0 { - self - } -} -"#, - expect![[r#"No references found at position"#]], - ); - } - - #[test] - fn test_rename_to_underscore() { - check("_", r#"fn main() { let i$0 = 1; }"#, r#"fn main() { let _ = 1; }"#); - } - - #[test] - fn test_rename_to_raw_identifier() { - check("r#fn", r#"fn main() { let i$0 = 1; }"#, r#"fn main() { let r#fn = 1; }"#); - } - - #[test] - fn test_rename_to_invalid_identifier1() { - check( - "invalid!", - r#"fn main() { let i$0 = 1; }"#, - "error: Invalid name `invalid!`: not an identifier", - ); - } - - #[test] - fn test_rename_to_invalid_identifier2() { - check( - "multiple tokens", - r#"fn main() { let i$0 = 1; }"#, - "error: Invalid name `multiple tokens`: not an identifier", - ); - } - - #[test] - fn test_rename_to_invalid_identifier3() { - check( - "let", - r#"fn main() { let i$0 = 1; }"#, - "error: Invalid name `let`: not an identifier", - ); - } - - #[test] - fn test_rename_to_invalid_identifier_lifetime() { - cov_mark::check!(rename_not_an_ident_ref); - check( - "'foo", - r#"fn main() { let i$0 = 1; }"#, - "error: Invalid name `'foo`: not an identifier", - ); - } - - #[test] - fn test_rename_to_invalid_identifier_lifetime2() { - cov_mark::check!(rename_not_a_lifetime_ident_ref); - check( - "foo", - r#"fn main<'a>(_: &'a$0 ()) {}"#, - "error: Invalid name `foo`: not a lifetime identifier", - ); - } - - #[test] - fn test_rename_to_underscore_invalid() { - cov_mark::check!(rename_underscore_multiple); - check( - "_", - r#"fn main(foo$0: ()) {foo;}"#, - "error: Cannot rename reference to `_` as it is being referenced multiple times", - ); - } - - #[test] - fn test_rename_mod_invalid() { - check( - "'foo", - r#"mod foo$0 {}"#, - "error: Invalid name `'foo`: cannot rename module to 'foo", - ); - } - - #[test] - fn test_rename_for_local() { - check( - "k", - r#" -fn main() { - let mut i = 1; - let j = 1; - i = i$0 + j; - - { i = 0; } - - i = 5; -} -"#, - r#" -fn main() { - let mut k = 1; - let j = 1; - k = k + j; - - { k = 0; } - - k = 5; -} -"#, - ); - } - - #[test] - fn test_rename_unresolved_reference() { - check( - "new_name", - r#"fn main() { let _ = unresolved_ref$0; }"#, - "error: No references found at position", - ); - } - - #[test] - fn test_rename_for_macro_args() { - check( - "b", - r#" -macro_rules! foo {($i:ident) => {$i} } -fn main() { - let a$0 = "test"; - foo!(a); -} -"#, - r#" -macro_rules! foo {($i:ident) => {$i} } -fn main() { - let b = "test"; - foo!(b); -} -"#, - ); - } - - #[test] - fn test_rename_for_macro_args_rev() { - check( - "b", - r#" -macro_rules! foo {($i:ident) => {$i} } -fn main() { - let a = "test"; - foo!(a$0); -} -"#, - r#" -macro_rules! foo {($i:ident) => {$i} } -fn main() { - let b = "test"; - foo!(b); -} -"#, - ); - } - - #[test] - fn test_rename_for_macro_define_fn() { - check( - "bar", - r#" -macro_rules! define_fn {($id:ident) => { fn $id{} }} -define_fn!(foo); -fn main() { - fo$0o(); -} -"#, - r#" -macro_rules! define_fn {($id:ident) => { fn $id{} }} -define_fn!(bar); -fn main() { - bar(); -} -"#, - ); - } - - #[test] - fn test_rename_for_macro_define_fn_rev() { - check( - "bar", - r#" -macro_rules! define_fn {($id:ident) => { fn $id{} }} -define_fn!(fo$0o); -fn main() { - foo(); -} -"#, - r#" -macro_rules! define_fn {($id:ident) => { fn $id{} }} -define_fn!(bar); -fn main() { - bar(); -} -"#, - ); - } - - #[test] - fn test_rename_for_param_inside() { - check("j", r#"fn foo(i : u32) -> u32 { i$0 }"#, r#"fn foo(j : u32) -> u32 { j }"#); - } - - #[test] - fn test_rename_refs_for_fn_param() { - check("j", r#"fn foo(i$0 : u32) -> u32 { i }"#, r#"fn foo(j : u32) -> u32 { j }"#); - } - - #[test] - fn test_rename_for_mut_param() { - check("j", r#"fn foo(mut i$0 : u32) -> u32 { i }"#, r#"fn foo(mut j : u32) -> u32 { j }"#); - } - - #[test] - fn test_rename_struct_field() { - check( - "j", - r#" -struct Foo { i$0: i32 } - -impl Foo { - fn new(i: i32) -> Self { - Self { i: i } - } -} -"#, - r#" -struct Foo { j: i32 } - -impl Foo { - fn new(i: i32) -> Self { - Self { j: i } - } -} -"#, - ); - } - - #[test] - fn test_rename_field_in_field_shorthand() { - cov_mark::check!(test_rename_field_in_field_shorthand); - check( - "j", - r#" -struct Foo { i$0: i32 } - -impl Foo { - fn new(i: i32) -> Self { - Self { i } - } -} -"#, - r#" -struct Foo { j: i32 } - -impl Foo { - fn new(i: i32) -> Self { - Self { j: i } - } -} -"#, - ); - } - - #[test] - fn test_rename_local_in_field_shorthand() { - cov_mark::check!(test_rename_local_in_field_shorthand); - check( - "j", - r#" -struct Foo { i: i32 } - -impl Foo { - fn new(i$0: i32) -> Self { - Self { i } - } -} -"#, - r#" -struct Foo { i: i32 } - -impl Foo { - fn new(j: i32) -> Self { - Self { i: j } - } -} -"#, - ); - } - - #[test] - fn test_field_shorthand_correct_struct() { - check( - "j", - r#" -struct Foo { i$0: i32 } -struct Bar { i: i32 } - -impl Bar { - fn new(i: i32) -> Self { - Self { i } - } -} -"#, - r#" -struct Foo { j: i32 } -struct Bar { i: i32 } - -impl Bar { - fn new(i: i32) -> Self { - Self { i } - } -} -"#, - ); - } - - #[test] - fn test_shadow_local_for_struct_shorthand() { - check( - "j", - r#" -struct Foo { i: i32 } - -fn baz(i$0: i32) -> Self { - let x = Foo { i }; - { - let i = 0; - Foo { i } - } -} -"#, - r#" -struct Foo { i: i32 } - -fn baz(j: i32) -> Self { - let x = Foo { i: j }; - { - let i = 0; - Foo { i } - } -} -"#, - ); - } - - #[test] - fn test_rename_mod() { - check_expect( - "foo2", - r#" -//- /lib.rs -mod bar; - -//- /bar.rs -mod foo$0; - -//- /bar/foo.rs -// empty -"#, - expect![[r#" - SourceChange { - source_file_edits: { - FileId( - 1, - ): TextEdit { - indels: [ - Indel { - insert: "foo2", - delete: 4..7, - }, - ], - }, - }, - file_system_edits: [ - MoveFile { - src: FileId( - 2, - ), - dst: AnchoredPathBuf { - anchor: FileId( - 2, - ), - path: "foo2.rs", - }, - }, - ], - is_snippet: false, - } - "#]], - ); - } - - #[test] - fn test_rename_mod_in_use_tree() { - check_expect( - "quux", - r#" -//- /main.rs -pub mod foo; -pub mod bar; -fn main() {} - -//- /foo.rs -pub struct FooContent; - -//- /bar.rs -use crate::foo$0::FooContent; -"#, - expect![[r#" - SourceChange { - source_file_edits: { - FileId( - 0, - ): TextEdit { - indels: [ - Indel { - insert: "quux", - delete: 8..11, - }, - ], - }, - FileId( - 2, - ): TextEdit { - indels: [ - Indel { - insert: "quux", - delete: 11..14, - }, - ], - }, - }, - file_system_edits: [ - MoveFile { - src: FileId( - 1, - ), - dst: AnchoredPathBuf { - anchor: FileId( - 1, - ), - path: "quux.rs", - }, - }, - ], - is_snippet: false, - } - "#]], - ); - } - - #[test] - fn test_rename_mod_in_dir() { - check_expect( - "foo2", - r#" -//- /lib.rs -mod fo$0o; -//- /foo/mod.rs -// empty -"#, - expect![[r#" - SourceChange { - source_file_edits: { - FileId( - 0, - ): TextEdit { - indels: [ - Indel { - insert: "foo2", - delete: 4..7, - }, - ], - }, - }, - file_system_edits: [ - MoveFile { - src: FileId( - 1, - ), - dst: AnchoredPathBuf { - anchor: FileId( - 1, - ), - path: "../foo2/mod.rs", - }, - }, - ], - is_snippet: false, - } - "#]], - ); - } - - #[test] - fn test_rename_unusually_nested_mod() { - check_expect( - "bar", - r#" -//- /lib.rs -mod outer { mod fo$0o; } - -//- /outer/foo.rs -// empty -"#, - expect![[r#" - SourceChange { - source_file_edits: { - FileId( - 0, - ): TextEdit { - indels: [ - Indel { - insert: "bar", - delete: 16..19, - }, - ], - }, - }, - file_system_edits: [ - MoveFile { - src: FileId( - 1, - ), - dst: AnchoredPathBuf { - anchor: FileId( - 1, - ), - path: "bar.rs", - }, - }, - ], - is_snippet: false, - } - "#]], - ); - } - - #[test] - fn test_module_rename_in_path() { - check( - "baz", - r#" -mod $0foo { pub fn bar() {} } - -fn main() { foo::bar(); } -"#, - r#" -mod baz { pub fn bar() {} } - -fn main() { baz::bar(); } -"#, - ); - } - - #[test] - fn test_rename_mod_filename_and_path() { - check_expect( - "foo2", - r#" -//- /lib.rs -mod bar; -fn f() { - bar::foo::fun() -} - -//- /bar.rs -pub mod foo$0; - -//- /bar/foo.rs -// pub fn fun() {} -"#, - expect![[r#" - SourceChange { - source_file_edits: { - FileId( - 0, - ): TextEdit { - indels: [ - Indel { - insert: "foo2", - delete: 27..30, - }, - ], - }, - FileId( - 1, - ): TextEdit { - indels: [ - Indel { - insert: "foo2", - delete: 8..11, - }, - ], - }, - }, - file_system_edits: [ - MoveFile { - src: FileId( - 2, - ), - dst: AnchoredPathBuf { - anchor: FileId( - 2, - ), - path: "foo2.rs", - }, - }, - ], - is_snippet: false, - } - "#]], - ); - } - - #[test] - fn test_enum_variant_from_module_1() { - cov_mark::check!(rename_non_local); - check( - "Baz", - r#" -mod foo { - pub enum Foo { Bar$0 } -} - -fn func(f: foo::Foo) { - match f { - foo::Foo::Bar => {} - } -} -"#, - r#" -mod foo { - pub enum Foo { Baz } -} - -fn func(f: foo::Foo) { - match f { - foo::Foo::Baz => {} - } -} -"#, - ); - } - - #[test] - fn test_enum_variant_from_module_2() { - check( - "baz", - r#" -mod foo { - pub struct Foo { pub bar$0: uint } -} - -fn foo(f: foo::Foo) { - let _ = f.bar; -} -"#, - r#" -mod foo { - pub struct Foo { pub baz: uint } -} - -fn foo(f: foo::Foo) { - let _ = f.baz; -} -"#, - ); - } - - #[test] - fn test_parameter_to_self() { - cov_mark::check!(rename_to_self); - check( - "self", - r#" -struct Foo { i: i32 } - -impl Foo { - fn f(foo$0: &mut Foo) -> i32 { - foo.i - } -} -"#, - r#" -struct Foo { i: i32 } - -impl Foo { - fn f(&mut self) -> i32 { - self.i - } -} -"#, - ); - check( - "self", - r#" -struct Foo { i: i32 } - -impl Foo { - fn f(foo$0: Foo) -> i32 { - foo.i - } -} -"#, - r#" -struct Foo { i: i32 } - -impl Foo { - fn f(self) -> i32 { - self.i - } -} -"#, - ); - } - - #[test] - fn test_parameter_to_self_error_no_impl() { - check( - "self", - r#" -struct Foo { i: i32 } - -fn f(foo$0: &mut Foo) -> i32 { - foo.i -} -"#, - "error: Cannot rename parameter to self for free function", - ); - check( - "self", - r#" -struct Foo { i: i32 } -struct Bar; - -impl Bar { - fn f(foo$0: &mut Foo) -> i32 { - foo.i - } -} -"#, - "error: Parameter type differs from impl block type", - ); - } - - #[test] - fn test_parameter_to_self_error_not_first() { - check( - "self", - r#" -struct Foo { i: i32 } -impl Foo { - fn f(x: (), foo$0: &mut Foo) -> i32 { - foo.i - } -} -"#, - "error: Only the first parameter may be renamed to self", - ); - } - - #[test] - fn test_parameter_to_self_impl_ref() { - check( - "self", - r#" -struct Foo { i: i32 } -impl &Foo { - fn f(foo$0: &Foo) -> i32 { - foo.i - } -} -"#, - r#" -struct Foo { i: i32 } -impl &Foo { - fn f(self) -> i32 { - self.i - } -} -"#, - ); - } - - #[test] - fn test_self_to_parameter() { - check( - "foo", - r#" -struct Foo { i: i32 } - -impl Foo { - fn f(&mut $0self) -> i32 { - self.i - } -} -"#, - r#" -struct Foo { i: i32 } - -impl Foo { - fn f(foo: &mut Foo) -> i32 { - foo.i - } -} -"#, - ); - } - - #[test] - fn test_owned_self_to_parameter() { - cov_mark::check!(rename_self_to_param); - check( - "foo", - r#" -struct Foo { i: i32 } - -impl Foo { - fn f($0self) -> i32 { - self.i - } -} -"#, - r#" -struct Foo { i: i32 } - -impl Foo { - fn f(foo: Foo) -> i32 { - foo.i - } -} -"#, - ); - } - - #[test] - fn test_self_in_path_to_parameter() { - check( - "foo", - r#" -struct Foo { i: i32 } - -impl Foo { - fn f(&self) -> i32 { - let self_var = 1; - self$0.i - } -} -"#, - r#" -struct Foo { i: i32 } - -impl Foo { - fn f(foo: &Foo) -> i32 { - let self_var = 1; - foo.i - } -} -"#, - ); - } - - #[test] - fn test_rename_field_put_init_shorthand() { - cov_mark::check!(test_rename_field_put_init_shorthand); - check( - "bar", - r#" -struct Foo { i$0: i32 } - -fn foo(bar: i32) -> Foo { - Foo { i: bar } -} -"#, - r#" -struct Foo { bar: i32 } - -fn foo(bar: i32) -> Foo { - Foo { bar } -} -"#, - ); - } - - #[test] - fn test_rename_local_put_init_shorthand() { - cov_mark::check!(test_rename_local_put_init_shorthand); - check( - "i", - r#" -struct Foo { i: i32 } - -fn foo(bar$0: i32) -> Foo { - Foo { i: bar } -} -"#, - r#" -struct Foo { i: i32 } - -fn foo(i: i32) -> Foo { - Foo { i } -} -"#, - ); - } - - #[test] - fn test_struct_field_pat_into_shorthand() { - cov_mark::check!(test_rename_field_put_init_shorthand_pat); - check( - "baz", - r#" -struct Foo { i$0: i32 } - -fn foo(foo: Foo) { - let Foo { i: ref baz @ qux } = foo; - let _ = qux; -} -"#, - r#" -struct Foo { baz: i32 } - -fn foo(foo: Foo) { - let Foo { ref baz @ qux } = foo; - let _ = qux; -} -"#, - ); - } - - #[test] - fn test_rename_binding_in_destructure_pat() { - let expected_fixture = r#" -struct Foo { - i: i32, -} - -fn foo(foo: Foo) { - let Foo { i: bar } = foo; - let _ = bar; -} -"#; - check( - "bar", - r#" -struct Foo { - i: i32, -} - -fn foo(foo: Foo) { - let Foo { i: b } = foo; - let _ = b$0; -} -"#, - expected_fixture, - ); - check( - "bar", - r#" -struct Foo { - i: i32, -} - -fn foo(foo: Foo) { - let Foo { i } = foo; - let _ = i$0; -} -"#, - expected_fixture, - ); - } - - #[test] - fn test_rename_binding_in_destructure_param_pat() { - check( - "bar", - r#" -struct Foo { - i: i32 -} - -fn foo(Foo { i }: foo) -> i32 { - i$0 -} -"#, - r#" -struct Foo { - i: i32 -} - -fn foo(Foo { i: bar }: foo) -> i32 { - bar -} -"#, - ) - } - - #[test] - fn test_struct_field_complex_ident_pat() { - check( - "baz", - r#" -struct Foo { i$0: i32 } - -fn foo(foo: Foo) { - let Foo { ref i } = foo; -} -"#, - r#" -struct Foo { baz: i32 } - -fn foo(foo: Foo) { - let Foo { baz: ref i } = foo; -} -"#, - ); - } - - #[test] - fn test_rename_lifetimes() { - cov_mark::check!(rename_lifetime); - check( - "'yeeee", - r#" -trait Foo<'a> { - fn foo() -> &'a (); -} -impl<'a> Foo<'a> for &'a () { - fn foo() -> &'a$0 () { - unimplemented!() - } -} -"#, - r#" -trait Foo<'a> { - fn foo() -> &'a (); -} -impl<'yeeee> Foo<'yeeee> for &'yeeee () { - fn foo() -> &'yeeee () { - unimplemented!() - } -} -"#, - ) - } - - #[test] - fn test_rename_bind_pat() { - check( - "new_name", - r#" -fn main() { - enum CustomOption { - None, - Some(T), - } - - let test_variable = CustomOption::Some(22); - - match test_variable { - CustomOption::Some(foo$0) if foo == 11 => {} - _ => (), - } -}"#, - r#" -fn main() { - enum CustomOption { - None, - Some(T), - } - - let test_variable = CustomOption::Some(22); - - match test_variable { - CustomOption::Some(new_name) if new_name == 11 => {} - _ => (), - } -}"#, - ); - } - - #[test] - fn test_rename_label() { - check( - "'foo", - r#" -fn foo<'a>() -> &'a () { - 'a: { - 'b: loop { - break 'a$0; - } - } -} -"#, - r#" -fn foo<'a>() -> &'a () { - 'foo: { - 'b: loop { - break 'foo; - } - } -} -"#, - ) - } - - #[test] - fn test_self_to_self() { - cov_mark::check!(rename_self_to_self); - check( - "self", - r#" -struct Foo; -impl Foo { - fn foo(self$0) {} -} -"#, - r#" -struct Foo; -impl Foo { - fn foo(self) {} -} -"#, - ) - } - - #[test] - fn test_rename_field_in_pat_in_macro_doesnt_shorthand() { - // ideally we would be able to make this emit a short hand, but I doubt this is easily possible - check( - "baz", - r#" -macro_rules! foo { - ($pattern:pat) => { - let $pattern = loop {}; - }; -} -struct Foo { - bar$0: u32, -} -fn foo() { - foo!(Foo { bar: baz }); -} -"#, - r#" -macro_rules! foo { - ($pattern:pat) => { - let $pattern = loop {}; - }; -} -struct Foo { - baz: u32, -} -fn foo() { - foo!(Foo { baz: baz }); -} -"#, - ) - } - - #[test] - fn test_rename_tuple_field() { - check( - "foo", - r#" -struct Foo(i32); - -fn baz() { - let mut x = Foo(4); - x.0$0 = 5; -} -"#, - "error: No identifier available to rename", - ); - } - - #[test] - fn test_rename_builtin() { - check( - "foo", - r#" -fn foo() { - let x: i32$0 = 0; -} -"#, - "error: Cannot rename builtin type", - ); - } - - #[test] - fn test_rename_self() { - check( - "foo", - r#" -struct Foo {} - -impl Foo { - fn foo(self) -> Self$0 { - self - } -} -"#, - "error: Cannot rename `Self`", - ); - } - - #[test] - fn test_rename_ignores_self_ty() { - check( - "Fo0", - r#" -struct $0Foo; - -impl Foo where Self: {} -"#, - r#" -struct Fo0; - -impl Fo0 where Self: {} -"#, - ); - } - - #[test] - fn test_rename_fails_on_aliases() { - check( - "Baz", - r#" -struct Foo; -use Foo as Bar$0; -"#, - "error: Renaming aliases is currently unsupported", - ); - check( - "Baz", - r#" -struct Foo; -use Foo as Bar; -use Bar$0; -"#, - "error: Renaming aliases is currently unsupported", - ); - } - - #[test] - fn test_rename_trait_method() { - let res = r" -trait Foo { - fn foo(&self) { - self.foo(); - } -} - -impl Foo for () { - fn foo(&self) { - self.foo(); - } -}"; - check( - "foo", - r#" -trait Foo { - fn bar$0(&self) { - self.bar(); - } -} - -impl Foo for () { - fn bar(&self) { - self.bar(); - } -}"#, - res, - ); - check( - "foo", - r#" -trait Foo { - fn bar(&self) { - self.bar$0(); - } -} - -impl Foo for () { - fn bar(&self) { - self.bar(); - } -}"#, - res, - ); - check( - "foo", - r#" -trait Foo { - fn bar(&self) { - self.bar(); - } -} - -impl Foo for () { - fn bar$0(&self) { - self.bar(); - } -}"#, - res, - ); - check( - "foo", - r#" -trait Foo { - fn bar(&self) { - self.bar(); - } -} - -impl Foo for () { - fn bar(&self) { - self.bar$0(); - } -}"#, - res, - ); - } - - #[test] - fn test_rename_trait_const() { - let res = r" -trait Foo { - const FOO: (); -} - -impl Foo for () { - const FOO: (); -} -fn f() { <()>::FOO; }"; - check( - "FOO", - r#" -trait Foo { - const BAR$0: (); -} - -impl Foo for () { - const BAR: (); -} -fn f() { <()>::BAR; }"#, - res, - ); - check( - "FOO", - r#" -trait Foo { - const BAR: (); -} - -impl Foo for () { - const BAR$0: (); -} -fn f() { <()>::BAR; }"#, - res, - ); - check( - "FOO", - r#" -trait Foo { - const BAR: (); -} - -impl Foo for () { - const BAR: (); -} -fn f() { <()>::BAR$0; }"#, - res, - ); - } - - #[test] - fn macros_are_broken_lol() { - cov_mark::check!(macros_are_broken_lol); - check( - "lol", - r#" -macro_rules! m { () => { fn f() {} } } -m!(); -fn main() { f$0() } -"#, - r#" -macro_rules! m { () => { fn f() {} } } -lol -fn main() { lol() } -"#, - ) - } -} -- cgit v1.2.3