Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-assists/src/handlers/move_from_mod_rs.rs')
| -rw-r--r-- | crates/ide-assists/src/handlers/move_from_mod_rs.rs | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/crates/ide-assists/src/handlers/move_from_mod_rs.rs b/crates/ide-assists/src/handlers/move_from_mod_rs.rs new file mode 100644 index 0000000000..b49c2e5da5 --- /dev/null +++ b/crates/ide-assists/src/handlers/move_from_mod_rs.rs @@ -0,0 +1,130 @@ +use ide_db::{ + assists::{AssistId, AssistKind}, + base_db::AnchoredPathBuf, +}; +use syntax::{ast, AstNode}; + +use crate::{ + assist_context::{AssistContext, Assists}, + utils::trimmed_text_range, +}; + +// Assist: move_from_mod_rs +// +// Moves xxx/mod.rs to xxx.rs. +// +// ``` +// //- /main.rs +// mod a; +// //- /a/mod.rs +// $0fn t() {}$0 +// ``` +// -> +// ``` +// fn t() {} +// ``` +pub(crate) fn move_from_mod_rs(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { + let source_file = ctx.find_node_at_offset::<ast::SourceFile>()?; + let module = ctx.sema.to_module_def(ctx.file_id())?; + // Enable this assist if the user select all "meaningful" content in the source file + let trimmed_selected_range = trimmed_text_range(&source_file, ctx.selection_trimmed()); + let trimmed_file_range = trimmed_text_range(&source_file, source_file.syntax().text_range()); + if !module.is_mod_rs(ctx.db()) { + cov_mark::hit!(not_mod_rs); + return None; + } + if trimmed_selected_range != trimmed_file_range { + cov_mark::hit!(not_all_selected); + return None; + } + + let target = source_file.syntax().text_range(); + let module_name = module.name(ctx.db())?.to_string(); + let path = format!("../{}.rs", module_name); + let dst = AnchoredPathBuf { anchor: ctx.file_id(), path }; + acc.add( + AssistId("move_from_mod_rs", AssistKind::Refactor), + format!("Convert {}/mod.rs to {}.rs", module_name, module_name), + target, + |builder| { + builder.move_file(ctx.file_id(), dst); + }, + ) +} + +#[cfg(test)] +mod tests { + use crate::tests::{check_assist, check_assist_not_applicable}; + + use super::*; + + #[test] + fn trivial() { + check_assist( + move_from_mod_rs, + r#" +//- /main.rs +mod a; +//- /a/mod.rs +$0fn t() {} +$0"#, + r#" +//- /a.rs +fn t() {} +"#, + ); + } + + #[test] + fn must_select_all_file() { + cov_mark::check!(not_all_selected); + check_assist_not_applicable( + move_from_mod_rs, + r#" +//- /main.rs +mod a; +//- /a/mod.rs +fn t() {}$0 +"#, + ); + cov_mark::check!(not_all_selected); + check_assist_not_applicable( + move_from_mod_rs, + r#" +//- /main.rs +mod a; +//- /a/mod.rs +$0fn$0 t() {} +"#, + ); + } + + #[test] + fn cannot_move_not_mod_rs() { + cov_mark::check!(not_mod_rs); + check_assist_not_applicable( + move_from_mod_rs, + r#"//- /main.rs +mod a; +//- /a.rs +$0fn t() {}$0 +"#, + ); + } + + #[test] + fn cannot_downgrade_main_and_lib_rs() { + check_assist_not_applicable( + move_from_mod_rs, + r#"//- /main.rs +$0fn t() {}$0 +"#, + ); + check_assist_not_applicable( + move_from_mod_rs, + r#"//- /lib.rs +$0fn t() {}$0 +"#, + ); + } +} |