aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/attr.rs
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2020-12-18 17:58:42 +0000
committerJonas Schievink <[email protected]>2020-12-18 17:58:42 +0000
commit08de1b4fa57ca78ad13026950b3eb024b7d2abf3 (patch)
tree99279afbe385ee36fdcd3921a4a89784439705cf /crates/hir_def/src/attr.rs
parent03c177af89efcc238053b59069eda2c1c6772622 (diff)
Implement `RawAttr::filter`
Diffstat (limited to 'crates/hir_def/src/attr.rs')
-rw-r--r--crates/hir_def/src/attr.rs64
1 files changed, 61 insertions, 3 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index 9cd0b72aa..b8d9c2682 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -122,9 +122,67 @@ impl RawAttrs {
122 } 122 }
123 123
124 /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`. 124 /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
125 pub(crate) fn filter(self, _db: &dyn DefDatabase, _krate: CrateId) -> Attrs { 125 pub(crate) fn filter(self, db: &dyn DefDatabase, krate: CrateId) -> Attrs {
126 // FIXME actually implement this 126 let has_cfg_attrs = self.iter().any(|attr| {
127 Attrs(self) 127 attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr])
128 });
129 if !has_cfg_attrs {
130 return Attrs(self);
131 }
132
133 let crate_graph = db.crate_graph();
134 let new_attrs = self
135 .iter()
136 .filter_map(|attr| {
137 let attr = attr.clone();
138 let is_cfg_attr =
139 attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr]);
140 if !is_cfg_attr {
141 return Some(attr);
142 }
143
144 let subtree = match &attr.input {
145 Some(AttrInput::TokenTree(it)) => it,
146 _ => return Some(attr),
147 };
148
149 // Input subtree is: `(cfg, attr)`
150 // Split it up into a `cfg` and an `attr` subtree.
151 // FIXME: There should be a common API for this.
152 let mut saw_comma = false;
153 let (mut cfg, attr): (Vec<_>, Vec<_>) =
154 subtree.clone().token_trees.into_iter().partition(|tree| {
155 if saw_comma {
156 return false;
157 }
158
159 match tree {
160 tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => {
161 saw_comma = true;
162 }
163 _ => {}
164 }
165
166 true
167 });
168 cfg.pop(); // `,` ends up in here
169
170 let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg };
171 let cfg = CfgExpr::parse(&cfg);
172
173 let cfg_options = &crate_graph[krate].cfg_options;
174 if cfg_options.check(&cfg) == Some(false) {
175 None
176 } else {
177 let attr = Subtree { delimiter: None, token_trees: attr };
178 let attr = ast::Attr::parse(&attr.to_string()).ok()?;
179 let hygiene = Hygiene::new_unhygienic(); // FIXME
180 Attr::from_src(attr, &hygiene)
181 }
182 })
183 .collect();
184
185 Attrs(RawAttrs { entries: Some(new_attrs) })
128 } 186 }
129} 187}
130 188