@@ -3,6 +3,7 @@ use std::collections::BTreeMap;
33use std:: path:: { Path , PathBuf } ;
44
55use rustc_ast:: ast;
6+ use rustc_ast:: attr:: HasAttrs ;
67use rustc_ast:: visit:: Visitor ;
78use rustc_span:: symbol:: { self , sym, Symbol } ;
89use thiserror:: Error ;
@@ -18,12 +19,48 @@ use crate::utils::contains_skip;
1819
1920mod visitor;
2021
21- type FileModMap < ' ast > = BTreeMap < FileName , Cow < ' ast , ast :: Mod > > ;
22+ type FileModMap < ' ast > = BTreeMap < FileName , Module < ' ast > > ;
2223
2324lazy_static ! {
2425 static ref CFG_IF : Symbol = Symbol :: intern( "cfg_if" ) ;
2526}
2627
28+ /// Represents module with its inner attributes.
29+ #[ derive( Debug , Clone ) ]
30+ pub ( crate ) struct Module < ' a > {
31+ ast_mod : Cow < ' a , ast:: Mod > ,
32+ inner_attr : Vec < ast:: Attribute > ,
33+ }
34+
35+ impl < ' a > Module < ' a > {
36+ pub ( crate ) fn new ( ast_mod : Cow < ' a , ast:: Mod > , attrs : & [ ast:: Attribute ] ) -> Self {
37+ let inner_attr = attrs
38+ . iter ( )
39+ . filter ( |attr| attr. style == ast:: AttrStyle :: Inner )
40+ . cloned ( )
41+ . collect ( ) ;
42+ Module {
43+ ast_mod,
44+ inner_attr,
45+ }
46+ }
47+ }
48+
49+ impl < ' a > HasAttrs for Module < ' a > {
50+ fn attrs ( & self ) -> & [ ast:: Attribute ] {
51+ & self . inner_attr
52+ }
53+ fn visit_attrs ( & mut self , f : impl FnOnce ( & mut Vec < ast:: Attribute > ) ) {
54+ f ( & mut self . inner_attr )
55+ }
56+ }
57+
58+ impl < ' a > AsRef < ast:: Mod > for Module < ' a > {
59+ fn as_ref ( & self ) -> & ast:: Mod {
60+ & self . ast_mod
61+ }
62+ }
63+
2764/// Maps each module to the corresponding file.
2865pub ( crate ) struct ModResolver < ' ast , ' sess > {
2966 parse_sess : & ' sess ParseSess ,
@@ -53,9 +90,9 @@ pub(crate) enum ModuleResolutionErrorKind {
5390#[ derive( Clone ) ]
5491enum SubModKind < ' a , ' ast > {
5592 /// `mod foo;`
56- External ( PathBuf , DirectoryOwnership , Cow < ' ast , ast :: Mod > ) ,
93+ External ( PathBuf , DirectoryOwnership , Module < ' ast > ) ,
5794 /// `mod foo;` with multiple sources.
58- MultiExternal ( Vec < ( PathBuf , DirectoryOwnership , Cow < ' ast , ast :: Mod > ) > ) ,
95+ MultiExternal ( Vec < ( PathBuf , DirectoryOwnership , Module < ' ast > ) > ) ,
5996 /// `mod foo {}`
6097 Internal ( & ' a ast:: Item ) ,
6198}
@@ -94,8 +131,10 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
94131 self . visit_mod_from_ast ( & krate. module ) ?;
95132 }
96133
97- self . file_map
98- . insert ( root_filename, Cow :: Borrowed ( & krate. module ) ) ;
134+ self . file_map . insert (
135+ root_filename,
136+ Module :: new ( Cow :: Borrowed ( & krate. module ) , & krate. attrs ) ,
137+ ) ;
99138 Ok ( self . file_map )
100139 }
101140
@@ -105,7 +144,10 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
105144 visitor. visit_item ( & item) ;
106145 for module_item in visitor. mods ( ) {
107146 if let ast:: ItemKind :: Mod ( ref sub_mod) = module_item. item . kind {
108- self . visit_sub_mod ( & module_item. item , Cow :: Owned ( sub_mod. clone ( ) ) ) ?;
147+ self . visit_sub_mod (
148+ & module_item. item ,
149+ Module :: new ( Cow :: Owned ( sub_mod. clone ( ) ) , & module_item. item . attrs ) ,
150+ ) ?;
109151 }
110152 }
111153 Ok ( ( ) )
@@ -120,7 +162,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
120162 }
121163
122164 if let ast:: ItemKind :: Mod ( ref sub_mod) = item. kind {
123- self . visit_sub_mod ( & item, Cow :: Owned ( sub_mod. clone ( ) ) ) ?;
165+ self . visit_sub_mod ( & item, Module :: new ( Cow :: Owned ( sub_mod. clone ( ) ) , & item . attrs ) ) ?;
124166 }
125167 }
126168 Ok ( ( ) )
@@ -134,7 +176,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
134176 }
135177
136178 if let ast:: ItemKind :: Mod ( ref sub_mod) = item. kind {
137- self . visit_sub_mod ( item, Cow :: Borrowed ( sub_mod) ) ?;
179+ self . visit_sub_mod ( item, Module :: new ( Cow :: Borrowed ( sub_mod) , & item . attrs ) ) ?;
138180 }
139181 }
140182 Ok ( ( ) )
@@ -143,12 +185,12 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
143185 fn visit_sub_mod (
144186 & mut self ,
145187 item : & ' c ast:: Item ,
146- sub_mod : Cow < ' ast , ast :: Mod > ,
188+ sub_mod : Module < ' ast > ,
147189 ) -> Result < ( ) , ModuleResolutionError > {
148190 let old_directory = self . directory . clone ( ) ;
149191 let sub_mod_kind = self . peek_sub_mod ( item, & sub_mod) ?;
150192 if let Some ( sub_mod_kind) = sub_mod_kind {
151- self . insert_sub_mod ( sub_mod_kind. clone ( ) , sub_mod . clone ( ) ) ?;
193+ self . insert_sub_mod ( sub_mod_kind. clone ( ) ) ?;
152194 self . visit_sub_mod_inner ( sub_mod, sub_mod_kind) ?;
153195 }
154196 self . directory = old_directory;
@@ -159,7 +201,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
159201 fn peek_sub_mod (
160202 & self ,
161203 item : & ' c ast:: Item ,
162- sub_mod : & Cow < ' ast , ast :: Mod > ,
204+ sub_mod : & Module < ' ast > ,
163205 ) -> Result < Option < SubModKind < ' c , ' ast > > , ModuleResolutionError > {
164206 if contains_skip ( & item. attrs ) {
165207 return Ok ( None ) ;
@@ -178,7 +220,6 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
178220 fn insert_sub_mod (
179221 & mut self ,
180222 sub_mod_kind : SubModKind < ' c , ' ast > ,
181- _sub_mod : Cow < ' ast , ast:: Mod > ,
182223 ) -> Result < ( ) , ModuleResolutionError > {
183224 match sub_mod_kind {
184225 SubModKind :: External ( mod_path, _, sub_mod) => {
@@ -200,7 +241,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
200241
201242 fn visit_sub_mod_inner (
202243 & mut self ,
203- sub_mod : Cow < ' ast , ast :: Mod > ,
244+ sub_mod : Module < ' ast > ,
204245 sub_mod_kind : SubModKind < ' c , ' ast > ,
205246 ) -> Result < ( ) , ModuleResolutionError > {
206247 match sub_mod_kind {
@@ -230,13 +271,13 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
230271
231272 fn visit_sub_mod_after_directory_update (
232273 & mut self ,
233- sub_mod : Cow < ' ast , ast :: Mod > ,
274+ sub_mod : Module < ' ast > ,
234275 directory : Option < Directory > ,
235276 ) -> Result < ( ) , ModuleResolutionError > {
236277 if let Some ( directory) = directory {
237278 self . directory = directory;
238279 }
239- match sub_mod {
280+ match sub_mod. ast_mod {
240281 Cow :: Borrowed ( sub_mod) => self . visit_mod_from_ast ( sub_mod) ,
241282 Cow :: Owned ( sub_mod) => self . visit_mod_outside_ast ( sub_mod) ,
242283 }
@@ -247,7 +288,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
247288 & self ,
248289 mod_name : symbol:: Ident ,
249290 attrs : & [ ast:: Attribute ] ,
250- sub_mod : & Cow < ' ast , ast :: Mod > ,
291+ sub_mod : & Module < ' ast > ,
251292 ) -> Result < Option < SubModKind < ' c , ' ast > > , ModuleResolutionError > {
252293 let relative = match self . directory . ownership {
253294 DirectoryOwnership :: Owned { relative } => relative,
@@ -257,12 +298,13 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
257298 if self . parse_sess . is_file_parsed ( & path) {
258299 return Ok ( None ) ;
259300 }
260- return match Parser :: parse_file_as_module ( self . parse_sess , & path, sub_mod. inner ) {
301+ return match Parser :: parse_file_as_module ( self . parse_sess , & path, sub_mod. ast_mod . inner )
302+ {
261303 Ok ( ( _, ref attrs) ) if contains_skip ( attrs) => Ok ( None ) ,
262- Ok ( ( m , _ ) ) => Ok ( Some ( SubModKind :: External (
304+ Ok ( m ) => Ok ( Some ( SubModKind :: External (
263305 path,
264306 DirectoryOwnership :: Owned { relative : None } ,
265- Cow :: Owned ( m) ,
307+ Module :: new ( Cow :: Owned ( m. 0 ) , & m . 1 ) ,
266308 ) ) ) ,
267309 Err ( ParserError :: ParseError ) => Err ( ModuleResolutionError {
268310 module : mod_name. to_string ( ) ,
@@ -300,13 +342,19 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
300342 return Ok ( Some ( SubModKind :: MultiExternal ( mods_outside_ast) ) ) ;
301343 }
302344 }
303- match Parser :: parse_file_as_module ( self . parse_sess , & path, sub_mod. inner ) {
345+ match Parser :: parse_file_as_module ( self . parse_sess , & path, sub_mod. ast_mod . inner ) {
304346 Ok ( ( _, ref attrs) ) if contains_skip ( attrs) => Ok ( None ) ,
305- Ok ( ( m, _) ) if outside_mods_empty => {
306- Ok ( Some ( SubModKind :: External ( path, ownership, Cow :: Owned ( m) ) ) )
307- }
308- Ok ( ( m, _) ) => {
309- mods_outside_ast. push ( ( path. clone ( ) , ownership, Cow :: Owned ( m) ) ) ;
347+ Ok ( m) if outside_mods_empty => Ok ( Some ( SubModKind :: External (
348+ path,
349+ ownership,
350+ Module :: new ( Cow :: Owned ( m. 0 ) , & m. 1 ) ,
351+ ) ) ) ,
352+ Ok ( m) => {
353+ mods_outside_ast. push ( (
354+ path. clone ( ) ,
355+ ownership,
356+ Module :: new ( Cow :: Owned ( m. 0 ) , & m. 1 ) ,
357+ ) ) ;
310358 if should_insert {
311359 mods_outside_ast. push ( ( path, ownership, sub_mod. clone ( ) ) ) ;
312360 }
@@ -368,8 +416,8 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
368416 fn find_mods_outside_of_ast (
369417 & self ,
370418 attrs : & [ ast:: Attribute ] ,
371- sub_mod : & Cow < ' ast , ast :: Mod > ,
372- ) -> Vec < ( PathBuf , DirectoryOwnership , Cow < ' ast , ast :: Mod > ) > {
419+ sub_mod : & Module < ' ast > ,
420+ ) -> Vec < ( PathBuf , DirectoryOwnership , Module < ' ast > ) > {
373421 // Filter nested path, like `#[cfg_attr(feature = "foo", path = "bar.rs")]`.
374422 let mut path_visitor = visitor:: PathVisitor :: default ( ) ;
375423 for attr in attrs. iter ( ) {
@@ -393,17 +441,20 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
393441 ) ) ;
394442 continue ;
395443 }
396- let m = match Parser :: parse_file_as_module ( self . parse_sess , & actual_path, sub_mod. inner )
397- {
444+ let m = match Parser :: parse_file_as_module (
445+ self . parse_sess ,
446+ & actual_path,
447+ sub_mod. ast_mod . inner ,
448+ ) {
398449 Ok ( ( _, ref attrs) ) if contains_skip ( attrs) => continue ,
399- Ok ( ( m , _ ) ) => m,
450+ Ok ( m ) => m,
400451 Err ( ..) => continue ,
401452 } ;
402453
403454 result. push ( (
404455 actual_path,
405456 DirectoryOwnership :: Owned { relative : None } ,
406- Cow :: Owned ( m) ,
457+ Module :: new ( Cow :: Owned ( m. 0 ) , & m . 1 ) ,
407458 ) )
408459 }
409460 result
0 commit comments