aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ide_assists/src/handlers/move_module_to_file.rs65
-rw-r--r--crates/syntax/src/ast/node_ext.rs8
2 files changed, 60 insertions, 13 deletions
diff --git a/crates/ide_assists/src/handlers/move_module_to_file.rs b/crates/ide_assists/src/handlers/move_module_to_file.rs
index 93f702c55..cfc54be8d 100644
--- a/crates/ide_assists/src/handlers/move_module_to_file.rs
+++ b/crates/ide_assists/src/handlers/move_module_to_file.rs
@@ -1,5 +1,8 @@
1use std::iter;
2
1use ast::edit::IndentLevel; 3use ast::edit::IndentLevel;
2use ide_db::base_db::AnchoredPathBuf; 4use ide_db::base_db::AnchoredPathBuf;
5use itertools::Itertools;
3use stdx::format_to; 6use stdx::format_to;
4use syntax::{ 7use syntax::{
5 ast::{self, edit::AstNodeEdit, NameOwner}, 8 ast::{self, edit::AstNodeEdit, NameOwner},
@@ -34,7 +37,10 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Opt
34 37
35 let module_name = module_ast.name()?; 38 let module_name = module_ast.name()?;
36 39
37 let module_def = ctx.sema.to_def(&module_ast)?; 40 // get to the outermost module syntax so we can grab the module of file we are in
41 let outermost_mod_decl =
42 iter::successors(Some(module_ast.clone()), |module| module.parent()).last()?;
43 let module_def = ctx.sema.to_def(&outermost_mod_decl)?;
38 let parent_module = module_def.parent(ctx.db())?; 44 let parent_module = module_def.parent(ctx.db())?;
39 45
40 acc.add( 46 acc.add(
@@ -43,11 +49,19 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Opt
43 target, 49 target,
44 |builder| { 50 |builder| {
45 let path = { 51 let path = {
46 let dir = match parent_module.name(ctx.db()) { 52 let mut buf = String::from("./");
47 Some(name) if !parent_module.is_mod_rs(ctx.db()) => format!("{}/", name), 53 match parent_module.name(ctx.db()) {
48 _ => String::new(), 54 Some(name) if !parent_module.is_mod_rs(ctx.db()) => {
49 }; 55 format_to!(buf, "{}/", name)
50 format!("./{}{}.rs", dir, module_name) 56 }
57 _ => (),
58 }
59 let segments = iter::successors(Some(module_ast.clone()), |module| module.parent())
60 .filter_map(|it| it.name())
61 .collect::<Vec<_>>();
62 format_to!(buf, "{}", segments.into_iter().rev().format("/"));
63 format_to!(buf, ".rs");
64 buf
51 }; 65 };
52 let contents = { 66 let contents = {
53 let items = module_items.dedent(IndentLevel(1)).to_string(); 67 let items = module_items.dedent(IndentLevel(1)).to_string();
@@ -59,14 +73,13 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Opt
59 items 73 items
60 }; 74 };
61 75
62 let mut buf = String::new(); 76 let buf = format!("mod {};", module_name);
63 format_to!(buf, "mod {};", module_name);
64 77
65 let replacement_start = if let Some(mod_token) = module_ast.mod_token() { 78 let replacement_start = match module_ast.mod_token() {
66 mod_token.text_range().start() 79 Some(mod_token) => mod_token.text_range(),
67 } else { 80 None => module_ast.syntax().text_range(),
68 module_ast.syntax().text_range().start() 81 }
69 }; 82 .start();
70 83
71 builder.replace( 84 builder.replace(
72 TextRange::new(replacement_start, module_ast.syntax().text_range().end()), 85 TextRange::new(replacement_start, module_ast.syntax().text_range().end()),
@@ -212,4 +225,30 @@ mod tests;
212"#, 225"#,
213 ); 226 );
214 } 227 }
228
229 #[test]
230 fn extract_nested() {
231 check_assist(
232 move_module_to_file,
233 r#"
234//- /lib.rs
235mod foo;
236//- /foo.rs
237mod bar {
238 mod baz {
239 mod qux$0 {}
240 }
241}
242"#,
243 r#"
244//- /foo.rs
245mod bar {
246 mod baz {
247 mod qux;
248 }
249}
250//- /foo/bar/baz/qux.rs
251"#,
252 );
253 }
215} 254}
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index 2bd9ad867..b057e6624 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -675,6 +675,14 @@ impl ast::LifetimeParam {
675 } 675 }
676} 676}
677 677
678impl ast::Module {
679 /// Returns the parent ast::Module, this is different than the semantic parent in that this only
680 /// considers parent declarations in the AST
681 pub fn parent(&self) -> Option<ast::Module> {
682 self.syntax().ancestors().nth(2).and_then(ast::Module::cast)
683 }
684}
685
678impl ast::RangePat { 686impl ast::RangePat {
679 pub fn start(&self) -> Option<ast::Pat> { 687 pub fn start(&self) -> Option<ast::Pat> {
680 self.syntax() 688 self.syntax()