Skip to content

Commit b28322e

Browse files
bors[bot]matklad
andauthored
Merge #7005
7005: Improve extract_module_to_file assist r=matklad a=matklad bors r+ 🤖 Co-authored-by: Aleksey Kladov <[email protected]>
2 parents 5506933 + 41bc323 commit b28322e

File tree

1 file changed

+66
-103
lines changed

1 file changed

+66
-103
lines changed
Lines changed: 66 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use ast::edit::IndentLevel;
2-
use ide_db::base_db::{AnchoredPathBuf, SourceDatabaseExt};
2+
use ide_db::base_db::AnchoredPathBuf;
33
use syntax::{
44
ast::{self, edit::AstNodeEdit, NameOwner},
55
AstNode,
@@ -21,43 +21,44 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
2121
// mod foo;
2222
// ```
2323
pub(crate) fn extract_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
24-
let assist_id = AssistId("extract_module_to_file", AssistKind::RefactorExtract);
25-
let assist_label = "Extract module to file";
26-
let db = ctx.db();
2724
let module_ast = ctx.find_node_at_offset::<ast::Module>()?;
28-
let module_items = module_ast.item_list()?;
29-
let dedent_module_items_text = module_items.dedent(IndentLevel(1)).to_string();
3025
let module_name = module_ast.name()?;
26+
27+
let module_def = ctx.sema.to_def(&module_ast)?;
28+
let parent_module = module_def.parent(ctx.db())?;
29+
30+
let module_items = module_ast.item_list()?;
3131
let target = module_ast.syntax().text_range();
3232
let anchor_file_id = ctx.frange.file_id;
33-
let sr = db.file_source_root(anchor_file_id);
34-
let sr = db.source_root(sr);
35-
let file_path = sr.path_for_file(&anchor_file_id)?;
36-
let (file_name, file_ext) = file_path.name_and_extension()?;
37-
acc.add(assist_id, assist_label, target, |builder| {
38-
builder.replace(target, format!("mod {};", module_name));
39-
let path = if is_main_or_lib(file_name) {
40-
format!("./{}.{}", module_name, file_ext.unwrap())
41-
} else {
42-
format!("./{}/{}.{}", file_name, module_name, file_ext.unwrap())
43-
};
44-
let dst = AnchoredPathBuf { anchor: anchor_file_id, path };
45-
let contents = update_module_items_string(dedent_module_items_text);
46-
builder.create_file(dst, contents);
47-
})
48-
}
49-
fn is_main_or_lib(file_name: &str) -> bool {
50-
file_name == "main".to_string() || file_name == "lib".to_string()
51-
}
52-
fn update_module_items_string(items_str: String) -> String {
53-
let mut items_string_lines: Vec<&str> = items_str.lines().collect();
54-
items_string_lines.pop(); // Delete last line
55-
items_string_lines.reverse();
56-
items_string_lines.pop(); // Delete first line
57-
items_string_lines.reverse();
5833

59-
let string = items_string_lines.join("\n");
60-
format!("{}", string)
34+
acc.add(
35+
AssistId("extract_module_to_file", AssistKind::RefactorExtract),
36+
"Extract module to file",
37+
target,
38+
|builder| {
39+
let path = {
40+
let dir = match parent_module.name(ctx.db()) {
41+
Some(name) if !parent_module.is_mod_rs(ctx.db()) => format!("{}/", name),
42+
_ => String::new(),
43+
};
44+
format!("./{}{}.rs", dir, module_name)
45+
};
46+
let contents = {
47+
let items = module_items.dedent(IndentLevel(1)).to_string();
48+
let mut items =
49+
items.trim_start_matches('{').trim_end_matches('}').trim().to_string();
50+
if !items.is_empty() {
51+
items.push('\n');
52+
}
53+
items
54+
};
55+
56+
builder.replace(target, format!("mod {};", module_name));
57+
58+
let dst = AnchoredPathBuf { anchor: anchor_file_id, path };
59+
builder.create_file(dst, contents);
60+
},
61+
)
6162
}
6263

6364
#[cfg(test)]
@@ -67,104 +68,66 @@ mod tests {
6768
use super::*;
6869

6970
#[test]
70-
fn extract_module_to_file_with_basic_module() {
71+
fn extract_from_root() {
7172
check_assist(
7273
extract_module_to_file,
7374
r#"
74-
//- /foo.rs crate:foo
7575
mod tests {<|>
7676
#[test] fn t() {}
7777
}
7878
"#,
7979
r#"
80-
//- /foo.rs
80+
//- /main.rs
8181
mod tests;
82-
//- /foo/tests.rs
83-
#[test] fn t() {}"#,
84-
)
85-
}
86-
87-
#[test]
88-
fn extract_module_to_file_with_file_path() {
89-
check_assist(
90-
extract_module_to_file,
91-
r#"
92-
//- /src/foo.rs crate:foo
93-
mod bar {<|>
94-
fn f() {
95-
96-
}
97-
}
98-
fn main() {
99-
println!("Hello, world!");
100-
}
82+
//- /tests.rs
83+
#[test] fn t() {}
10184
"#,
102-
r#"
103-
//- /src/foo.rs
104-
mod bar;
105-
fn main() {
106-
println!("Hello, world!");
107-
}
108-
//- /src/foo/bar.rs
109-
fn f() {
110-
111-
}"#,
112-
)
85+
);
11386
}
11487

11588
#[test]
116-
fn extract_module_to_file_with_main_filw() {
89+
fn extract_from_submodule() {
11790
check_assist(
11891
extract_module_to_file,
11992
r#"
12093
//- /main.rs
121-
mod foo {<|>
122-
fn f() {
123-
124-
}
125-
}
126-
fn main() {
127-
println!("Hello, world!");
94+
mod submodule;
95+
//- /submodule.rs
96+
mod inner<|> {
97+
fn f() {}
12898
}
99+
fn g() {}
129100
"#,
130101
r#"
131-
//- /main.rs
132-
mod foo;
133-
fn main() {
134-
println!("Hello, world!");
135-
}
136-
//- /foo.rs
137-
fn f() {
138-
139-
}"#,
140-
)
102+
//- /submodule.rs
103+
mod inner;
104+
fn g() {}
105+
//- /submodule/inner.rs
106+
fn f() {}
107+
"#,
108+
);
141109
}
142110

143111
#[test]
144-
fn extract_module_to_file_with_lib_file() {
112+
fn extract_from_mod_rs() {
145113
check_assist(
146114
extract_module_to_file,
147115
r#"
148-
//- /lib.rs
149-
mod foo {<|>
150-
fn f() {
151-
152-
}
153-
}
154-
fn main() {
155-
println!("Hello, world!");
116+
//- /main.rs
117+
mod submodule;
118+
//- /submodule/mod.rs
119+
mod inner<|> {
120+
fn f() {}
156121
}
122+
fn g() {}
157123
"#,
158124
r#"
159-
//- /lib.rs
160-
mod foo;
161-
fn main() {
162-
println!("Hello, world!");
163-
}
164-
//- /foo.rs
165-
fn f() {
166-
167-
}"#,
168-
)
125+
//- /submodule/mod.rs
126+
mod inner;
127+
fn g() {}
128+
//- /submodule/inner.rs
129+
fn f() {}
130+
"#,
131+
);
169132
}
170133
}

0 commit comments

Comments
 (0)