@@ -12,6 +12,7 @@ use syntax::{
1212 ast:: { self , AstNode , AttrsOwner } ,
1313 match_ast, AstToken , SmolStr , SyntaxNode ,
1414} ;
15+ use test_utils:: mark;
1516use tt:: Subtree ;
1617
1718use crate :: {
@@ -122,9 +123,69 @@ impl RawAttrs {
122123 }
123124
124125 /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
125- pub ( crate ) fn filter ( self , _db : & dyn DefDatabase , _krate : CrateId ) -> Attrs {
126- // FIXME actually implement this
127- Attrs ( self )
126+ pub ( crate ) fn filter ( self , db : & dyn DefDatabase , krate : CrateId ) -> Attrs {
127+ let has_cfg_attrs = self . iter ( ) . any ( |attr| {
128+ attr. path . as_ident ( ) . map_or ( false , |name| * name == hir_expand:: name![ cfg_attr] )
129+ } ) ;
130+ if !has_cfg_attrs {
131+ return Attrs ( self ) ;
132+ }
133+
134+ let crate_graph = db. crate_graph ( ) ;
135+ let new_attrs = self
136+ . iter ( )
137+ . filter_map ( |attr| {
138+ let attr = attr. clone ( ) ;
139+ let is_cfg_attr =
140+ attr. path . as_ident ( ) . map_or ( false , |name| * name == hir_expand:: name![ cfg_attr] ) ;
141+ if !is_cfg_attr {
142+ return Some ( attr) ;
143+ }
144+
145+ let subtree = match & attr. input {
146+ Some ( AttrInput :: TokenTree ( it) ) => it,
147+ _ => return Some ( attr) ,
148+ } ;
149+
150+ // Input subtree is: `(cfg, attr)`
151+ // Split it up into a `cfg` and an `attr` subtree.
152+ // FIXME: There should be a common API for this.
153+ let mut saw_comma = false ;
154+ let ( mut cfg, attr) : ( Vec < _ > , Vec < _ > ) =
155+ subtree. clone ( ) . token_trees . into_iter ( ) . partition ( |tree| {
156+ if saw_comma {
157+ return false ;
158+ }
159+
160+ match tree {
161+ tt:: TokenTree :: Leaf ( tt:: Leaf :: Punct ( p) ) if p. char == ',' => {
162+ saw_comma = true ;
163+ }
164+ _ => { }
165+ }
166+
167+ true
168+ } ) ;
169+ cfg. pop ( ) ; // `,` ends up in here
170+
171+ let attr = Subtree { delimiter : None , token_trees : attr } ;
172+ let cfg = Subtree { delimiter : subtree. delimiter , token_trees : cfg } ;
173+ let cfg = CfgExpr :: parse ( & cfg) ;
174+
175+ let cfg_options = & crate_graph[ krate] . cfg_options ;
176+ if cfg_options. check ( & cfg) == Some ( false ) {
177+ None
178+ } else {
179+ mark:: hit!( cfg_attr_active) ;
180+
181+ let attr = ast:: Attr :: parse ( & format ! ( "#[{}]" , attr) ) . ok ( ) ?;
182+ let hygiene = Hygiene :: new_unhygienic ( ) ; // FIXME
183+ Attr :: from_src ( attr, & hygiene)
184+ }
185+ } )
186+ . collect ( ) ;
187+
188+ Attrs ( RawAttrs { entries : Some ( new_attrs) } )
128189 }
129190}
130191
0 commit comments