aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_assists/src/handlers/move_module_to_file.rs
diff options
context:
space:
mode:
authorChetan Khilosiya <[email protected]>2021-02-22 18:47:48 +0000
committerChetan Khilosiya <[email protected]>2021-02-22 19:29:16 +0000
commite4756cb4f6e66097638b9d101589358976be2ba8 (patch)
treeb6ca0ae6b45b57834476ae0f9985cec3a6bd9090 /crates/ide_assists/src/handlers/move_module_to_file.rs
parent8687053b118f47ce1a4962d0baa19b22d40d2758 (diff)
7526: Rename crate assists to ide_assists.
Diffstat (limited to 'crates/ide_assists/src/handlers/move_module_to_file.rs')
-rw-r--r--crates/ide_assists/src/handlers/move_module_to_file.rs188
1 files changed, 188 insertions, 0 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
new file mode 100644
index 000000000..91c395c1b
--- /dev/null
+++ b/crates/ide_assists/src/handlers/move_module_to_file.rs
@@ -0,0 +1,188 @@
1use ast::{edit::IndentLevel, VisibilityOwner};
2use ide_db::base_db::AnchoredPathBuf;
3use stdx::format_to;
4use syntax::{
5 ast::{self, edit::AstNodeEdit, NameOwner},
6 AstNode, TextRange,
7};
8use test_utils::mark;
9
10use crate::{AssistContext, AssistId, AssistKind, Assists};
11
12// Assist: move_module_to_file
13//
14// Moves inline module's contents to a separate file.
15//
16// ```
17// mod $0foo {
18// fn t() {}
19// }
20// ```
21// ->
22// ```
23// mod foo;
24// ```
25pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
26 let module_ast = ctx.find_node_at_offset::<ast::Module>()?;
27 let module_items = module_ast.item_list()?;
28
29 let l_curly_offset = module_items.syntax().text_range().start();
30 if l_curly_offset <= ctx.offset() {
31 mark::hit!(available_before_curly);
32 return None;
33 }
34 let target = TextRange::new(module_ast.syntax().text_range().start(), l_curly_offset);
35
36 let module_name = module_ast.name()?;
37
38 let module_def = ctx.sema.to_def(&module_ast)?;
39 let parent_module = module_def.parent(ctx.db())?;
40
41 acc.add(
42 AssistId("move_module_to_file", AssistKind::RefactorExtract),
43 "Extract module to file",
44 target,
45 |builder| {
46 let path = {
47 let dir = match parent_module.name(ctx.db()) {
48 Some(name) if !parent_module.is_mod_rs(ctx.db()) => format!("{}/", name),
49 _ => String::new(),
50 };
51 format!("./{}{}.rs", dir, module_name)
52 };
53 let contents = {
54 let items = module_items.dedent(IndentLevel(1)).to_string();
55 let mut items =
56 items.trim_start_matches('{').trim_end_matches('}').trim().to_string();
57 if !items.is_empty() {
58 items.push('\n');
59 }
60 items
61 };
62
63 let mut buf = String::new();
64 if let Some(v) = module_ast.visibility() {
65 format_to!(buf, "{} ", v);
66 }
67 format_to!(buf, "mod {};", module_name);
68
69 builder.replace(module_ast.syntax().text_range(), buf);
70
71 let dst = AnchoredPathBuf { anchor: ctx.frange.file_id, path };
72 builder.create_file(dst, contents);
73 },
74 )
75}
76
77#[cfg(test)]
78mod tests {
79 use crate::tests::{check_assist, check_assist_not_applicable};
80
81 use super::*;
82
83 #[test]
84 fn extract_from_root() {
85 check_assist(
86 move_module_to_file,
87 r#"
88mod $0tests {
89 #[test] fn t() {}
90}
91"#,
92 r#"
93//- /main.rs
94mod tests;
95//- /tests.rs
96#[test] fn t() {}
97"#,
98 );
99 }
100
101 #[test]
102 fn extract_from_submodule() {
103 check_assist(
104 move_module_to_file,
105 r#"
106//- /main.rs
107mod submod;
108//- /submod.rs
109$0mod inner {
110 fn f() {}
111}
112fn g() {}
113"#,
114 r#"
115//- /submod.rs
116mod inner;
117fn g() {}
118//- /submod/inner.rs
119fn f() {}
120"#,
121 );
122 }
123
124 #[test]
125 fn extract_from_mod_rs() {
126 check_assist(
127 move_module_to_file,
128 r#"
129//- /main.rs
130mod submodule;
131//- /submodule/mod.rs
132mod inner$0 {
133 fn f() {}
134}
135fn g() {}
136"#,
137 r#"
138//- /submodule/mod.rs
139mod inner;
140fn g() {}
141//- /submodule/inner.rs
142fn f() {}
143"#,
144 );
145 }
146
147 #[test]
148 fn extract_public() {
149 check_assist(
150 move_module_to_file,
151 r#"
152pub mod $0tests {
153 #[test] fn t() {}
154}
155"#,
156 r#"
157//- /main.rs
158pub mod tests;
159//- /tests.rs
160#[test] fn t() {}
161"#,
162 );
163 }
164
165 #[test]
166 fn extract_public_crate() {
167 check_assist(
168 move_module_to_file,
169 r#"
170pub(crate) mod $0tests {
171 #[test] fn t() {}
172}
173"#,
174 r#"
175//- /main.rs
176pub(crate) mod tests;
177//- /tests.rs
178#[test] fn t() {}
179"#,
180 );
181 }
182
183 #[test]
184 fn available_before_curly() {
185 mark::check!(available_before_curly);
186 check_assist_not_applicable(move_module_to_file, r#"mod m { $0 }"#);
187 }
188}