From 25edc3c60a8fe9a01b1ff7b6a20ceb83d78e2965 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 6 Jan 2021 16:24:47 +0300 Subject: Better target for move module --- .../assists/src/handlers/extract_module_to_file.rs | 133 ------------------- crates/assists/src/handlers/move_module_to_file.rs | 145 +++++++++++++++++++++ crates/assists/src/lib.rs | 4 +- crates/assists/src/tests/generated.rs | 30 ++--- 4 files changed, 162 insertions(+), 150 deletions(-) delete mode 100644 crates/assists/src/handlers/extract_module_to_file.rs create mode 100644 crates/assists/src/handlers/move_module_to_file.rs diff --git a/crates/assists/src/handlers/extract_module_to_file.rs b/crates/assists/src/handlers/extract_module_to_file.rs deleted file mode 100644 index 50bf67ef7..000000000 --- a/crates/assists/src/handlers/extract_module_to_file.rs +++ /dev/null @@ -1,133 +0,0 @@ -use ast::edit::IndentLevel; -use ide_db::base_db::AnchoredPathBuf; -use syntax::{ - ast::{self, edit::AstNodeEdit, NameOwner}, - AstNode, -}; - -use crate::{AssistContext, AssistId, AssistKind, Assists}; - -// Assist: extract_module_to_file -// -// This assist extract module to file. -// -// ``` -// mod foo {<|> -// fn t() {} -// } -// ``` -// -> -// ``` -// mod foo; -// ``` -pub(crate) fn extract_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { - let module_ast = ctx.find_node_at_offset::()?; - let module_name = module_ast.name()?; - - let module_def = ctx.sema.to_def(&module_ast)?; - let parent_module = module_def.parent(ctx.db())?; - - let module_items = module_ast.item_list()?; - let target = module_ast.syntax().text_range(); - let anchor_file_id = ctx.frange.file_id; - - acc.add( - AssistId("extract_module_to_file", AssistKind::RefactorExtract), - "Extract module to file", - target, - |builder| { - let path = { - let dir = match parent_module.name(ctx.db()) { - Some(name) if !parent_module.is_mod_rs(ctx.db()) => format!("{}/", name), - _ => String::new(), - }; - format!("./{}{}.rs", dir, module_name) - }; - let contents = { - let items = module_items.dedent(IndentLevel(1)).to_string(); - let mut items = - items.trim_start_matches('{').trim_end_matches('}').trim().to_string(); - if !items.is_empty() { - items.push('\n'); - } - items - }; - - builder.replace(target, format!("mod {};", module_name)); - - let dst = AnchoredPathBuf { anchor: anchor_file_id, path }; - builder.create_file(dst, contents); - }, - ) -} - -#[cfg(test)] -mod tests { - use crate::tests::check_assist; - - use super::*; - - #[test] - fn extract_from_root() { - check_assist( - extract_module_to_file, - r#" -mod tests {<|> - #[test] fn t() {} -} -"#, - r#" -//- /main.rs -mod tests; -//- /tests.rs -#[test] fn t() {} -"#, - ); - } - - #[test] - fn extract_from_submodule() { - check_assist( - extract_module_to_file, - r#" -//- /main.rs -mod submod; -//- /submod.rs -mod inner<|> { - fn f() {} -} -fn g() {} -"#, - r#" -//- /submod.rs -mod inner; -fn g() {} -//- /submod/inner.rs -fn f() {} -"#, - ); - } - - #[test] - fn extract_from_mod_rs() { - check_assist( - extract_module_to_file, - r#" -//- /main.rs -mod submodule; -//- /submodule/mod.rs -mod inner<|> { - fn f() {} -} -fn g() {} -"#, - r#" -//- /submodule/mod.rs -mod inner; -fn g() {} -//- /submodule/inner.rs -fn f() {} -"#, - ); - } -} diff --git a/crates/assists/src/handlers/move_module_to_file.rs b/crates/assists/src/handlers/move_module_to_file.rs new file mode 100644 index 000000000..165faaf61 --- /dev/null +++ b/crates/assists/src/handlers/move_module_to_file.rs @@ -0,0 +1,145 @@ +use ast::edit::IndentLevel; +use ide_db::base_db::AnchoredPathBuf; +use syntax::{ + ast::{self, edit::AstNodeEdit, NameOwner}, + AstNode, TextRange, +}; +use test_utils::mark; + +use crate::{AssistContext, AssistId, AssistKind, Assists}; + +// Assist: move_module_to_file +// +// Moves inline module's contents to a separate file. +// +// ``` +// mod <|>foo { +// fn t() {} +// } +// ``` +// -> +// ``` +// mod foo; +// ``` +pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { + let module_ast = ctx.find_node_at_offset::()?; + let module_items = module_ast.item_list()?; + + let l_curly_offset = module_items.syntax().text_range().start(); + if l_curly_offset <= ctx.offset() { + mark::hit!(available_before_curly); + return None; + } + let target = TextRange::new(module_ast.syntax().text_range().start(), l_curly_offset); + + let module_name = module_ast.name()?; + + let module_def = ctx.sema.to_def(&module_ast)?; + let parent_module = module_def.parent(ctx.db())?; + + acc.add( + AssistId("move_module_to_file", AssistKind::RefactorExtract), + "Extract module to file", + target, + |builder| { + let path = { + let dir = match parent_module.name(ctx.db()) { + Some(name) if !parent_module.is_mod_rs(ctx.db()) => format!("{}/", name), + _ => String::new(), + }; + format!("./{}{}.rs", dir, module_name) + }; + let contents = { + let items = module_items.dedent(IndentLevel(1)).to_string(); + let mut items = + items.trim_start_matches('{').trim_end_matches('}').trim().to_string(); + if !items.is_empty() { + items.push('\n'); + } + items + }; + + builder.replace(module_ast.syntax().text_range(), format!("mod {};", module_name)); + + let dst = AnchoredPathBuf { anchor: ctx.frange.file_id, path }; + builder.create_file(dst, contents); + }, + ) +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::*; + + #[test] + fn extract_from_root() { + check_assist( + move_module_to_file, + r#" +mod <|>tests { + #[test] fn t() {} +} +"#, + r#" +//- /main.rs +mod tests; +//- /tests.rs +#[test] fn t() {} +"#, + ); + } + + #[test] + fn extract_from_submodule() { + check_assist( + move_module_to_file, + r#" +//- /main.rs +mod submod; +//- /submod.rs +<|>mod inner { + fn f() {} +} +fn g() {} +"#, + r#" +//- /submod.rs +mod inner; +fn g() {} +//- /submod/inner.rs +fn f() {} +"#, + ); + } + + #[test] + fn extract_from_mod_rs() { + check_assist( + move_module_to_file, + r#" +//- /main.rs +mod submodule; +//- /submodule/mod.rs +mod inner<|> { + fn f() {} +} +fn g() {} +"#, + r#" +//- /submodule/mod.rs +mod inner; +fn g() {} +//- /submodule/inner.rs +fn f() {} +"#, + ); + } + + #[test] + fn available_before_curly() { + mark::check!(available_before_curly); + check_assist_not_applicable(move_module_to_file, r#"mod m { <|> }"#); + } +} diff --git a/crates/assists/src/lib.rs b/crates/assists/src/lib.rs index 9c2a95735..5e3a1b368 100644 --- a/crates/assists/src/lib.rs +++ b/crates/assists/src/lib.rs @@ -116,7 +116,6 @@ mod handlers { mod convert_integer_literal; mod early_return; mod expand_glob_import; - mod extract_module_to_file; mod extract_struct_from_enum_variant; mod extract_variable; mod fill_match_arms; @@ -139,6 +138,7 @@ mod handlers { mod merge_match_arms; mod move_bounds; mod move_guard; + mod move_module_to_file; mod pull_assignment_up; mod qualify_path; mod raw_string; @@ -169,7 +169,7 @@ mod handlers { convert_integer_literal::convert_integer_literal, early_return::convert_to_guarded_return, expand_glob_import::expand_glob_import, - extract_module_to_file::extract_module_to_file, + move_module_to_file::move_module_to_file, extract_struct_from_enum_variant::extract_struct_from_enum_variant, extract_variable::extract_variable, fill_match_arms::fill_match_arms, diff --git a/crates/assists/src/tests/generated.rs b/crates/assists/src/tests/generated.rs index b15352cf3..fdebee4fe 100644 --- a/crates/assists/src/tests/generated.rs +++ b/crates/assists/src/tests/generated.rs @@ -237,21 +237,6 @@ fn qux(bar: Bar, baz: Baz) {} ) } -#[test] -fn doctest_extract_module_to_file() { - check_doc_test( - "extract_module_to_file", - r#####" -mod foo {<|> - fn t() {} -} -"#####, - r#####" -mod foo; -"#####, - ) -} - #[test] fn doctest_extract_struct_from_enum_variant() { check_doc_test( @@ -760,6 +745,21 @@ fn handle(action: Action) { ) } +#[test] +fn doctest_move_module_to_file() { + check_doc_test( + "move_module_to_file", + r#####" +mod <|>foo { + fn t() {} +} +"#####, + r#####" +mod foo; +"#####, + ) +} + #[test] fn doctest_pull_assignment_up() { check_doc_test( -- cgit v1.2.3