@@ -3,12 +3,38 @@ use ide_db::{
33 base_db:: AnchoredPathBuf ,
44} ;
55use syntax:: {
6- ast:: { self } ,
7- AstNode , TextRange ,
6+ ast:: { self , Whitespace } ,
7+ AstNode , AstToken , SourceFile , TextRange , TextSize ,
88} ;
99
1010use crate :: assist_context:: { AssistContext , Assists } ;
1111
12+ /// Trim(remove leading and trailing whitespace) `initial_range` in `source_file`, return the trimmed range.
13+ fn trimmed_text_range ( source_file : & SourceFile , initial_range : TextRange ) -> TextRange {
14+ let mut trimmed_range = initial_range;
15+ while source_file
16+ . syntax ( )
17+ . token_at_offset ( trimmed_range. start ( ) )
18+ . find_map ( Whitespace :: cast)
19+ . is_some ( )
20+ && trimmed_range. start ( ) < trimmed_range. end ( )
21+ {
22+ let start = trimmed_range. start ( ) + TextSize :: from ( 1 ) ;
23+ trimmed_range = TextRange :: new ( start, trimmed_range. end ( ) ) ;
24+ }
25+ while source_file
26+ . syntax ( )
27+ . token_at_offset ( trimmed_range. end ( ) )
28+ . find_map ( Whitespace :: cast)
29+ . is_some ( )
30+ && trimmed_range. start ( ) < trimmed_range. end ( )
31+ {
32+ let end = trimmed_range. end ( ) - TextSize :: from ( 1 ) ;
33+ trimmed_range = TextRange :: new ( trimmed_range. start ( ) , end) ;
34+ }
35+ trimmed_range
36+ }
37+
1238// Assist: promote_mod_file
1339//
1440// Moves inline module's contents to a separate file.
@@ -17,7 +43,7 @@ use crate::assist_context::{AssistContext, Assists};
1743// //- /main.rs
1844// mod a;
1945// //- /a.rs
20- // $0fn t() {}
46+ // $0fn t() {}$0
2147// ```
2248// ->
2349// ```
@@ -26,18 +52,23 @@ use crate::assist_context::{AssistContext, Assists};
2652pub ( crate ) fn promote_mod_file ( acc : & mut Assists , ctx : & AssistContext ) -> Option < ( ) > {
2753 let source_file = ctx. find_node_at_offset :: < ast:: SourceFile > ( ) ?;
2854 let module = ctx. sema . to_module_def ( ctx. frange . file_id ) ?;
29- if module. is_mod_rs ( ctx. db ( ) ) {
55+ // Enable this assist if the user select all "meaningful" content in the source file
56+ let trimmed_selected_range = trimmed_text_range ( & source_file, ctx. frange . range ) ;
57+ let trimmed_file_range = trimmed_text_range ( & source_file, source_file. syntax ( ) . text_range ( ) ) ;
58+ if module. is_mod_rs ( ctx. db ( ) ) || trimmed_selected_range != trimmed_file_range {
3059 return None ;
3160 }
61+
3262 let target = TextRange :: new (
3363 source_file. syntax ( ) . text_range ( ) . start ( ) ,
3464 source_file. syntax ( ) . text_range ( ) . end ( ) ,
3565 ) ;
36- let path = format ! ( "./{}/mod.rs" , module. name( ctx. db( ) ) ?. to_string( ) ) ;
66+ let module_name = module. name ( ctx. db ( ) ) ?. to_string ( ) ;
67+ let path = format ! ( "./{}/mod.rs" , module_name) ;
3768 let dst = AnchoredPathBuf { anchor : ctx. frange . file_id , path } ;
3869 acc. add (
3970 AssistId ( "promote_mod_file" , AssistKind :: Refactor ) ,
40- "Promote Module to directory" ,
71+ format ! ( "Turn {}.rs to {}/mod.rs" , module_name , module_name ) ,
4172 target,
4273 |builder| {
4374 builder. move_file ( ctx. frange . file_id , dst) ;
@@ -60,7 +91,7 @@ mod tests {
6091mod a;
6192//- /a.rs
6293$0fn t() {}
63- "# ,
94+ $0 "#,
6495 r#"
6596//- /a/mod.rs
6697fn t() {}
@@ -69,44 +100,23 @@ fn t() {}
69100 }
70101
71102 #[ test]
72- fn cursor_can_be_putted_anywhere ( ) {
73- check_assist (
103+ fn must_select_all_file ( ) {
104+ check_assist_not_applicable (
74105 promote_mod_file,
75106 r#"
76107//- /main.rs
77108mod a;
78109//- /a.rs
79110fn t() {}$0
80- "# ,
81- r#"
82- //- /a/mod.rs
83- fn t() {}
84111"# ,
85112 ) ;
86- check_assist (
87- promote_mod_file,
88- r#"
89- //- /main.rs
90- mod a;
91- //- /a.rs
92- fn t()$0 {}
93- "# ,
94- r#"
95- //- /a/mod.rs
96- fn t() {}
97- "# ,
98- ) ;
99- check_assist (
113+ check_assist_not_applicable (
100114 promote_mod_file,
101115 r#"
102116//- /main.rs
103117mod a;
104118//- /a.rs
105- fn t($0) {}
106- "# ,
107- r#"
108- //- /a/mod.rs
109- fn t() {}
119+ $0fn$0 t() {}
110120"# ,
111121 ) ;
112122 }
@@ -147,8 +157,8 @@ $0fn t() {}
147157 r#"//- /main.rs
148158mod a;
149159//- /a.rs
150- mod b;
151- $0fn t() {}
160+ $0mod b;
161+ fn t() {}$0
152162//- /a/b.rs
153163fn t1() {}
154164"# ,
0 commit comments