diff options
Diffstat (limited to 'crates/hir_def/src/attr.rs')
-rw-r--r-- | crates/hir_def/src/attr.rs | 67 |
1 files changed, 64 insertions, 3 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 9cd0b72aa..1b9c64ee5 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -12,6 +12,7 @@ use syntax::{ | |||
12 | ast::{self, AstNode, AttrsOwner}, | 12 | ast::{self, AstNode, AttrsOwner}, |
13 | match_ast, AstToken, SmolStr, SyntaxNode, | 13 | match_ast, AstToken, SmolStr, SyntaxNode, |
14 | }; | 14 | }; |
15 | use test_utils::mark; | ||
15 | use tt::Subtree; | 16 | use tt::Subtree; |
16 | 17 | ||
17 | use crate::{ | 18 | use crate::{ |
@@ -122,9 +123,69 @@ impl RawAttrs { | |||
122 | } | 123 | } |
123 | 124 | ||
124 | /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`. | 125 | /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`. |
125 | pub(crate) fn filter(self, _db: &dyn DefDatabase, _krate: CrateId) -> Attrs { | 126 | pub(crate) fn filter(self, db: &dyn DefDatabase, krate: CrateId) -> Attrs { |
126 | // FIXME actually implement this | 127 | let has_cfg_attrs = self.iter().any(|attr| { |
127 | Attrs(self) | 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) }) | ||
128 | } | 189 | } |
129 | } | 190 | } |
130 | 191 | ||