diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-06-17 11:10:25 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-06-17 11:10:25 +0100 |
commit | 3b58d8f785917b4212cd917fced6c3006210e4d3 (patch) | |
tree | ffe4d1ea9ff0d43956f27959f86dc7d878b72481 | |
parent | 8ff46a368cbaad4f7ae28a2b19b7dde59ed75111 (diff) | |
parent | cd5f4121e3bfb345f730bdce4106450e728f9721 (diff) |
Merge #9308
9308: fix: Create modules in correct directory for nested modules in move_module assist r=Veykril a=Veykril
bors r+
Co-authored-by: Lukas Wirth <[email protected]>
-rw-r--r-- | crates/ide_assists/src/handlers/move_module_to_file.rs | 65 | ||||
-rw-r--r-- | crates/syntax/src/ast/node_ext.rs | 8 |
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 @@ | |||
1 | use std::iter; | ||
2 | |||
1 | use ast::edit::IndentLevel; | 3 | use ast::edit::IndentLevel; |
2 | use ide_db::base_db::AnchoredPathBuf; | 4 | use ide_db::base_db::AnchoredPathBuf; |
5 | use itertools::Itertools; | ||
3 | use stdx::format_to; | 6 | use stdx::format_to; |
4 | use syntax::{ | 7 | use 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 | ||
235 | mod foo; | ||
236 | //- /foo.rs | ||
237 | mod bar { | ||
238 | mod baz { | ||
239 | mod qux$0 {} | ||
240 | } | ||
241 | } | ||
242 | "#, | ||
243 | r#" | ||
244 | //- /foo.rs | ||
245 | mod 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 | ||
678 | impl 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 | |||
678 | impl ast::RangePat { | 686 | impl ast::RangePat { |
679 | pub fn start(&self) -> Option<ast::Pat> { | 687 | pub fn start(&self) -> Option<ast::Pat> { |
680 | self.syntax() | 688 | self.syntax() |