]> git.lizzy.rs Git - rust.git/blob - crates/ide_assists/src/handlers/promote_mod_file.rs
Add promote_mod_file assist
[rust.git] / crates / ide_assists / src / handlers / promote_mod_file.rs
1 use ide_db::{
2     assists::{AssistId, AssistKind},
3     base_db::AnchoredPathBuf,
4 };
5 use syntax::{
6     ast::{self},
7     AstNode, TextRange,
8 };
9
10 use crate::assist_context::{AssistContext, Assists};
11
12 pub(crate) fn promote_mod_file(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
13     let source_file = ctx.find_node_at_offset::<ast::SourceFile>()?;
14     let module = ctx.sema.to_module_def(ctx.frange.file_id)?;
15     if module.is_mod_rs(ctx.db()) {
16         return None;
17     }
18     let target = TextRange::new(
19         source_file.syntax().text_range().start(),
20         source_file.syntax().text_range().end(),
21     );
22     let path = format!("./{}/mod.rs", module.name(ctx.db())?.to_string());
23     let dst = AnchoredPathBuf { anchor: ctx.frange.file_id, path };
24     acc.add(
25         AssistId("promote_mod_file", AssistKind::Refactor),
26         "Promote Module to directory",
27         target,
28         |builder| {
29             builder.move_file(ctx.frange.file_id, dst);
30         },
31     )
32 }
33
34 #[cfg(test)]
35 mod tests {
36     use crate::tests::{check_assist, check_assist_not_applicable};
37
38     use super::*;
39
40     #[test]
41     fn trivial() {
42         check_assist(
43             promote_mod_file,
44             r#"
45 //- /main.rs
46 mod a;
47 //- /a.rs
48 $0fn t() {}
49 "#,
50             r#"
51 //- /a/mod.rs
52 fn t() {}
53 "#,
54         );
55     }
56
57     #[test]
58     fn cursor_can_be_putted_anywhere() {
59         check_assist(
60             promote_mod_file,
61             r#"
62 //- /main.rs
63 mod a;
64 //- /a.rs
65 fn t() {}$0
66 "#,
67             r#"
68 //- /a/mod.rs
69 fn t() {}
70 "#,
71         );
72         check_assist(
73             promote_mod_file,
74             r#"
75 //- /main.rs
76 mod a;
77 //- /a.rs
78 fn t()$0 {}
79 "#,
80             r#"
81 //- /a/mod.rs
82 fn t() {}
83 "#,
84         );
85         check_assist(
86             promote_mod_file,
87             r#"
88 //- /main.rs
89 mod a;
90 //- /a.rs
91 fn t($0) {}
92 "#,
93             r#"
94 //- /a/mod.rs
95 fn t() {}
96 "#,
97         );
98     }
99
100     #[test]
101     fn cannot_promote_mod_rs() {
102         check_assist_not_applicable(
103             promote_mod_file,
104             r#"//- /main.rs
105 mod a;
106 //- /a/mod.rs
107 $0fn t() {}
108 "#,
109         );
110     }
111
112     #[test]
113     fn cannot_promote_main_and_lib_rs() {
114         check_assist_not_applicable(
115             promote_mod_file,
116             r#"//- /main.rs
117 $0fn t() {}
118 "#,
119         );
120         check_assist_not_applicable(
121             promote_mod_file,
122             r#"//- /lib.rs
123 $0fn t() {}
124 "#,
125         );
126     }
127
128     #[test]
129     fn works_in_mod() {
130         // note: /a/b.rs remains untouched
131         check_assist(
132             promote_mod_file,
133             r#"//- /main.rs
134 mod a;
135 //- /a.rs
136 mod b;
137 $0fn t() {}
138 //- /a/b.rs
139 fn t1() {}
140 "#,
141             r#"
142 //- /a/mod.rs
143 mod b;
144 fn t() {}
145 "#,
146         );
147     }
148 }