mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 04:53:34 +00:00
Create modules in correct directory for nested modules in move_module assist
This commit is contained in:
parent
d6b8af4482
commit
cd5f4121e3
2 changed files with 60 additions and 13 deletions
|
@ -1,5 +1,8 @@
|
||||||
|
use std::iter;
|
||||||
|
|
||||||
use ast::edit::IndentLevel;
|
use ast::edit::IndentLevel;
|
||||||
use ide_db::base_db::AnchoredPathBuf;
|
use ide_db::base_db::AnchoredPathBuf;
|
||||||
|
use itertools::Itertools;
|
||||||
use stdx::format_to;
|
use stdx::format_to;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, edit::AstNodeEdit, NameOwner},
|
ast::{self, edit::AstNodeEdit, NameOwner},
|
||||||
|
@ -34,7 +37,10 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Opt
|
||||||
|
|
||||||
let module_name = module_ast.name()?;
|
let module_name = module_ast.name()?;
|
||||||
|
|
||||||
let module_def = ctx.sema.to_def(&module_ast)?;
|
// get to the outermost module syntax so we can grab the module of file we are in
|
||||||
|
let outermost_mod_decl =
|
||||||
|
iter::successors(Some(module_ast.clone()), |module| module.parent()).last()?;
|
||||||
|
let module_def = ctx.sema.to_def(&outermost_mod_decl)?;
|
||||||
let parent_module = module_def.parent(ctx.db())?;
|
let parent_module = module_def.parent(ctx.db())?;
|
||||||
|
|
||||||
acc.add(
|
acc.add(
|
||||||
|
@ -43,11 +49,19 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Opt
|
||||||
target,
|
target,
|
||||||
|builder| {
|
|builder| {
|
||||||
let path = {
|
let path = {
|
||||||
let dir = match parent_module.name(ctx.db()) {
|
let mut buf = String::from("./");
|
||||||
Some(name) if !parent_module.is_mod_rs(ctx.db()) => format!("{}/", name),
|
match parent_module.name(ctx.db()) {
|
||||||
_ => String::new(),
|
Some(name) if !parent_module.is_mod_rs(ctx.db()) => {
|
||||||
};
|
format_to!(buf, "{}/", name)
|
||||||
format!("./{}{}.rs", dir, module_name)
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
let segments = iter::successors(Some(module_ast.clone()), |module| module.parent())
|
||||||
|
.filter_map(|it| it.name())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
format_to!(buf, "{}", segments.into_iter().rev().format("/"));
|
||||||
|
format_to!(buf, ".rs");
|
||||||
|
buf
|
||||||
};
|
};
|
||||||
let contents = {
|
let contents = {
|
||||||
let items = module_items.dedent(IndentLevel(1)).to_string();
|
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
|
||||||
items
|
items
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut buf = String::new();
|
let buf = format!("mod {};", module_name);
|
||||||
format_to!(buf, "mod {};", module_name);
|
|
||||||
|
|
||||||
let replacement_start = if let Some(mod_token) = module_ast.mod_token() {
|
let replacement_start = match module_ast.mod_token() {
|
||||||
mod_token.text_range().start()
|
Some(mod_token) => mod_token.text_range(),
|
||||||
} else {
|
None => module_ast.syntax().text_range(),
|
||||||
module_ast.syntax().text_range().start()
|
}
|
||||||
};
|
.start();
|
||||||
|
|
||||||
builder.replace(
|
builder.replace(
|
||||||
TextRange::new(replacement_start, module_ast.syntax().text_range().end()),
|
TextRange::new(replacement_start, module_ast.syntax().text_range().end()),
|
||||||
|
@ -209,6 +222,32 @@ mod $0tests {
|
||||||
mod tests;
|
mod tests;
|
||||||
//- /tests.rs
|
//- /tests.rs
|
||||||
#[test] fn t() {}
|
#[test] fn t() {}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn extract_nested() {
|
||||||
|
check_assist(
|
||||||
|
move_module_to_file,
|
||||||
|
r#"
|
||||||
|
//- /lib.rs
|
||||||
|
mod foo;
|
||||||
|
//- /foo.rs
|
||||||
|
mod bar {
|
||||||
|
mod baz {
|
||||||
|
mod qux$0 {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
//- /foo.rs
|
||||||
|
mod bar {
|
||||||
|
mod baz {
|
||||||
|
mod qux;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//- /foo/bar/baz/qux.rs
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -675,6 +675,14 @@ impl ast::LifetimeParam {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ast::Module {
|
||||||
|
/// Returns the parent ast::Module, this is different than the semantic parent in that this only
|
||||||
|
/// considers parent declarations in the AST
|
||||||
|
pub fn parent(&self) -> Option<ast::Module> {
|
||||||
|
self.syntax().ancestors().nth(2).and_then(ast::Module::cast)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ast::RangePat {
|
impl ast::RangePat {
|
||||||
pub fn start(&self) -> Option<ast::Pat> {
|
pub fn start(&self) -> Option<ast::Pat> {
|
||||||
self.syntax()
|
self.syntax()
|
||||||
|
|
Loading…
Reference in a new issue