@@ -40,6 +40,15 @@ impl<'a> Directory {
40
40
}
41
41
}
42
42
43
+ enum SubModKind {
44
+ /// `mod foo;`
45
+ External ( PathBuf , DirectoryOwnership ) ,
46
+ /// `#[path = "..."] mod foo {}`
47
+ InternalWithPath ( PathBuf ) ,
48
+ /// `mod foo {}`
49
+ Internal ,
50
+ }
51
+
43
52
impl < ' ast , ' sess , ' c > ModResolver < ' ast , ' sess > {
44
53
/// Creates a new `ModResolver`.
45
54
pub ( crate ) fn new (
@@ -91,11 +100,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
91
100
visitor. visit_item ( & item) ;
92
101
for module_item in visitor. mods ( ) {
93
102
if let ast:: ItemKind :: Mod ( ref sub_mod) = module_item. item . node {
94
- let cow_sub_mod = Cow :: Owned ( sub_mod. clone ( ) ) ;
95
- if let Some ( old_directory) = self . peek_sub_mod ( & module_item. item , & cow_sub_mod) ? {
96
- self . visit_mod_from_macro ( cow_sub_mod) ?;
97
- self . directory = old_directory;
98
- }
103
+ self . visit_mod_inner ( & item, Cow :: Owned ( sub_mod. clone ( ) ) ) ?;
99
104
}
100
105
}
101
106
Ok ( ( ) )
@@ -109,16 +114,24 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
109
114
}
110
115
111
116
if let ast:: ItemKind :: Mod ( ref sub_mod) = item. node {
112
- let cow_sub_mod = Cow :: Owned ( sub_mod. clone ( ) ) ;
113
- if let Some ( old_directory) = self . peek_sub_mod ( item, & cow_sub_mod) ? {
114
- self . visit_mod_from_macro ( cow_sub_mod) ?;
115
- self . directory = old_directory;
116
- }
117
+ self . visit_mod_inner ( item, Cow :: Owned ( sub_mod. clone ( ) ) ) ?;
117
118
}
118
119
}
119
120
Ok ( ( ) )
120
121
}
121
122
123
+ fn visit_mod_inner (
124
+ & mut self ,
125
+ item : & ' c ast:: Item ,
126
+ sub_mod : Cow < ' ast , ast:: Mod > ,
127
+ ) -> Result < ( ) , String > {
128
+ let old_directory = self . directory . clone ( ) ;
129
+ self . visit_sub_mod ( item, & sub_mod) ?;
130
+ self . visit_mod_from_macro ( sub_mod) ?;
131
+ self . directory = old_directory;
132
+ Ok ( ( ) )
133
+ }
134
+
122
135
/// Visit modules from AST.
123
136
fn visit_mod_from_ast ( & mut self , module : & ' ast ast:: Mod ) -> Result < ( ) , String > {
124
137
for item in & module. items {
@@ -127,58 +140,62 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
127
140
}
128
141
129
142
if let ast:: ItemKind :: Mod ( ref sub_mod) = item. node {
130
- if let Some ( old_directory) = self . peek_sub_mod ( item, & Cow :: Borrowed ( sub_mod) ) ? {
131
- self . visit_mod_from_ast ( sub_mod) ?;
132
- self . directory = old_directory;
133
- }
143
+ self . visit_mod_inner ( item, Cow :: Borrowed ( sub_mod) ) ?;
134
144
}
135
145
}
136
146
Ok ( ( ) )
137
147
}
138
148
139
- /// Inspect the given sub-module which we are about to visit and update the state of
140
- /// `ModResolver` based on the kind of the sub-module.
141
- /// Returns an error if we cannot find a file that corresponds to the sub-module.
142
- /// Returns one of the followings on success:
143
- /// - If we should not visit the sub-module (e.g., it has #[rustfmt::skip]), `Ok(None)`.
144
- /// - If we should visit the sub-module, `Some(Directory)`, which should be restored after
145
- /// visiting the sub-module.
146
- fn peek_sub_mod (
149
+ fn visit_sub_mod (
147
150
& mut self ,
148
151
item : & ' c ast:: Item ,
149
152
sub_mod : & Cow < ' ast , ast:: Mod > ,
150
- ) -> Result < Option < Directory > , String > {
153
+ ) -> Result < ( ) , String > {
154
+ match self . peek_sub_mod ( item) ? {
155
+ Some ( SubModKind :: External ( mod_path, directory_ownership) ) => {
156
+ self . file_map . insert (
157
+ FileName :: Real ( mod_path. clone ( ) ) ,
158
+ ( sub_mod. clone ( ) , item. ident . name . as_str ( ) . get ( ) . to_owned ( ) ) ,
159
+ ) ;
160
+ self . directory = Directory {
161
+ path : mod_path. parent ( ) . unwrap ( ) . to_path_buf ( ) ,
162
+ ownership : directory_ownership,
163
+ } ;
164
+ }
165
+ Some ( SubModKind :: InternalWithPath ( mod_path) ) => {
166
+ // All `#[path]` files are treated as though they are a `mod.rs` file.
167
+ self . directory = Directory {
168
+ path : mod_path,
169
+ ownership : DirectoryOwnership :: Owned { relative : None } ,
170
+ } ;
171
+ }
172
+ Some ( SubModKind :: Internal ) => self . push_inline_mod_directory ( item. ident , & item. attrs ) ,
173
+ None => ( ) , // rustfmt::skip
174
+ }
175
+ Ok ( ( ) )
176
+ }
177
+
178
+ /// Inspect the given sub-module which we are about to visit and returns its kind.
179
+ fn peek_sub_mod ( & self , item : & ' c ast:: Item ) -> Result < Option < SubModKind > , String > {
151
180
if contains_skip ( & item. attrs ) {
152
181
return Ok ( None ) ;
153
182
}
154
183
155
- let old_directory = self . directory . clone ( ) ;
156
184
if is_mod_decl ( item) {
157
185
// mod foo;
158
186
// Look for an extern file.
159
187
let ( mod_path, directory_ownership) =
160
188
self . find_external_module ( item. ident , & item. attrs ) ?;
161
- self . file_map . insert (
162
- FileName :: Real ( mod_path. clone ( ) ) ,
163
- ( sub_mod. clone ( ) , item. ident . name . as_str ( ) . get ( ) . to_owned ( ) ) ,
164
- ) ;
165
- self . directory = Directory {
166
- path : mod_path. parent ( ) . unwrap ( ) . to_path_buf ( ) ,
167
- ownership : directory_ownership,
168
- }
189
+ Ok ( Some ( SubModKind :: External ( mod_path, directory_ownership) ) )
169
190
} else {
170
191
// An internal module (`mod foo { /* ... */ }`);
171
192
if let Some ( path) = find_path_value ( & item. attrs ) {
172
- // All `#[path]` files are treated as though they are a `mod.rs` file.
173
- self . directory = Directory {
174
- path : Path :: new ( & path. as_str ( ) ) . to_path_buf ( ) ,
175
- ownership : DirectoryOwnership :: Owned { relative : None } ,
176
- } ;
193
+ let path = Path :: new ( & path. as_str ( ) ) . to_path_buf ( ) ;
194
+ Ok ( Some ( SubModKind :: InternalWithPath ( path) ) )
177
195
} else {
178
- self . push_inline_mod_directory ( item . ident , & item . attrs ) ;
196
+ Ok ( Some ( SubModKind :: Internal ) )
179
197
}
180
198
}
181
- Ok ( Some ( old_directory) )
182
199
}
183
200
184
201
/// Find a file path in the filesystem which corresponds to the given module.
0 commit comments