@@ -5,7 +5,7 @@ use hir::Semantics;
5
5
use syntax:: {
6
6
algo,
7
7
ast:: { self , make, AstNode , AttrsOwner , ModuleItemOwner , PathSegmentKind , VisibilityOwner } ,
8
- ted, AstToken , Direction , NodeOrToken , SyntaxNode , SyntaxToken ,
8
+ match_ast , ted, AstToken , Direction , NodeOrToken , SyntaxNode , SyntaxToken ,
9
9
} ;
10
10
11
11
use crate :: {
@@ -43,16 +43,32 @@ pub struct InsertUseConfig {
43
43
pub enum ImportScope {
44
44
File ( ast:: SourceFile ) ,
45
45
Module ( ast:: ItemList ) ,
46
+ Block ( ast:: BlockExpr ) ,
46
47
}
47
48
48
49
impl ImportScope {
49
- pub fn from ( syntax : SyntaxNode ) -> Option < Self > {
50
- if let Some ( module) = ast:: Module :: cast ( syntax. clone ( ) ) {
51
- module. item_list ( ) . map ( ImportScope :: Module )
52
- } else if let this @ Some ( _) = ast:: SourceFile :: cast ( syntax. clone ( ) ) {
53
- this. map ( ImportScope :: File )
54
- } else {
55
- ast:: ItemList :: cast ( syntax) . map ( ImportScope :: Module )
50
+ fn from ( syntax : SyntaxNode ) -> Option < Self > {
51
+ fn contains_cfg_attr ( attrs : & dyn AttrsOwner ) -> bool {
52
+ attrs
53
+ . attrs ( )
54
+ . any ( |attr| attr. as_simple_call ( ) . map_or ( false , |( ident, _) | ident == "cfg" ) )
55
+ }
56
+ match_ast ! {
57
+ match syntax {
58
+ ast:: Module ( module) => module. item_list( ) . map( ImportScope :: Module ) ,
59
+ ast:: SourceFile ( file) => Some ( ImportScope :: File ( file) ) ,
60
+ ast:: Fn ( func) => contains_cfg_attr( & func) . then( || func. body( ) . map( ImportScope :: Block ) ) . flatten( ) ,
61
+ ast:: Const ( konst) => contains_cfg_attr( & konst) . then( || match konst. body( ) ? {
62
+ ast:: Expr :: BlockExpr ( block) => Some ( block) ,
63
+ _ => None ,
64
+ } ) . flatten( ) . map( ImportScope :: Block ) ,
65
+ ast:: Static ( statik) => contains_cfg_attr( & statik) . then( || match statik. body( ) ? {
66
+ ast:: Expr :: BlockExpr ( block) => Some ( block) ,
67
+ _ => None ,
68
+ } ) . flatten( ) . map( ImportScope :: Block ) ,
69
+ _ => None ,
70
+
71
+ }
56
72
}
57
73
}
58
74
@@ -73,13 +89,15 @@ impl ImportScope {
73
89
match self {
74
90
ImportScope :: File ( file) => file. syntax ( ) ,
75
91
ImportScope :: Module ( item_list) => item_list. syntax ( ) ,
92
+ ImportScope :: Block ( block) => block. syntax ( ) ,
76
93
}
77
94
}
78
95
79
96
pub fn clone_for_update ( & self ) -> Self {
80
97
match self {
81
98
ImportScope :: File ( file) => ImportScope :: File ( file. clone_for_update ( ) ) ,
82
99
ImportScope :: Module ( item_list) => ImportScope :: Module ( item_list. clone_for_update ( ) ) ,
100
+ ImportScope :: Block ( block) => ImportScope :: Block ( block. clone_for_update ( ) ) ,
83
101
}
84
102
}
85
103
@@ -96,6 +114,7 @@ impl ImportScope {
96
114
let mut use_stmts = match self {
97
115
ImportScope :: File ( f) => f. items ( ) ,
98
116
ImportScope :: Module ( m) => m. items ( ) ,
117
+ ImportScope :: Block ( b) => b. items ( ) ,
99
118
}
100
119
. filter_map ( use_stmt) ;
101
120
let mut res = ImportGranularityGuess :: Unknown ;
@@ -319,28 +338,29 @@ fn insert_use_(
319
338
ted:: insert ( ted:: Position :: after ( last_inner_element) , make:: tokens:: single_newline ( ) ) ;
320
339
return ;
321
340
}
322
- match scope {
341
+ let l_curly = match scope {
323
342
ImportScope :: File ( _) => {
324
343
cov_mark:: hit!( insert_group_empty_file) ;
325
344
ted:: insert ( ted:: Position :: first_child_of ( scope_syntax) , make:: tokens:: blank_line ( ) ) ;
326
- ted:: insert ( ted:: Position :: first_child_of ( scope_syntax) , use_item. syntax ( ) )
345
+ ted:: insert ( ted:: Position :: first_child_of ( scope_syntax) , use_item. syntax ( ) ) ;
346
+ return ;
327
347
}
348
+ // don't insert the imports before the item list/block expr's opening curly brace
349
+ ImportScope :: Module ( item_list) => item_list. l_curly_token ( ) ,
328
350
// don't insert the imports before the item list's opening curly brace
329
- ImportScope :: Module ( item_list) => match item_list. l_curly_token ( ) {
330
- Some ( b) => {
331
- cov_mark:: hit!( insert_group_empty_module) ;
332
- ted:: insert ( ted:: Position :: after ( & b) , make:: tokens:: single_newline ( ) ) ;
333
- ted:: insert ( ted:: Position :: after ( & b) , use_item. syntax ( ) ) ;
334
- }
335
- None => {
336
- // This should never happens, broken module syntax node
337
- ted:: insert (
338
- ted:: Position :: first_child_of ( scope_syntax) ,
339
- make:: tokens:: blank_line ( ) ,
340
- ) ;
341
- ted:: insert ( ted:: Position :: first_child_of ( scope_syntax) , use_item. syntax ( ) ) ;
342
- }
343
- } ,
351
+ ImportScope :: Block ( block) => block. l_curly_token ( ) ,
352
+ } ;
353
+ match l_curly {
354
+ Some ( b) => {
355
+ cov_mark:: hit!( insert_group_empty_module) ;
356
+ ted:: insert ( ted:: Position :: after ( & b) , make:: tokens:: single_newline ( ) ) ;
357
+ ted:: insert ( ted:: Position :: after ( & b) , use_item. syntax ( ) ) ;
358
+ }
359
+ None => {
360
+ // This should never happens, broken module syntax node
361
+ ted:: insert ( ted:: Position :: first_child_of ( scope_syntax) , make:: tokens:: blank_line ( ) ) ;
362
+ ted:: insert ( ted:: Position :: first_child_of ( scope_syntax) , use_item. syntax ( ) ) ;
363
+ }
344
364
}
345
365
}
346
366
0 commit comments