diff options
Diffstat (limited to 'crates/hir_def')
-rw-r--r-- | crates/hir_def/src/attr.rs | 48 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 12 | ||||
-rw-r--r-- | crates/hir_def/src/lib.rs | 10 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/diagnostics.rs | 3 | ||||
-rw-r--r-- | crates/hir_def/src/test_db.rs | 9 |
5 files changed, 34 insertions, 48 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 97cdbbb9e..7b41b148c 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -9,6 +9,7 @@ use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile}; | |||
9 | use itertools::Itertools; | 9 | use itertools::Itertools; |
10 | use la_arena::ArenaMap; | 10 | use la_arena::ArenaMap; |
11 | use mbe::ast_to_token_tree; | 11 | use mbe::ast_to_token_tree; |
12 | use smallvec::{smallvec, SmallVec}; | ||
12 | use syntax::{ | 13 | use syntax::{ |
13 | ast::{self, AstNode, AttrsOwner}, | 14 | ast::{self, AstNode, AttrsOwner}, |
14 | match_ast, AstToken, SmolStr, SyntaxNode, | 15 | match_ast, AstToken, SmolStr, SyntaxNode, |
@@ -134,53 +135,42 @@ impl RawAttrs { | |||
134 | let crate_graph = db.crate_graph(); | 135 | let crate_graph = db.crate_graph(); |
135 | let new_attrs = self | 136 | let new_attrs = self |
136 | .iter() | 137 | .iter() |
137 | .filter_map(|attr| { | 138 | .flat_map(|attr| -> SmallVec<[_; 1]> { |
138 | let attr = attr.clone(); | 139 | let attr = attr.clone(); |
139 | let is_cfg_attr = | 140 | let is_cfg_attr = |
140 | attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr]); | 141 | attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr]); |
141 | if !is_cfg_attr { | 142 | if !is_cfg_attr { |
142 | return Some(attr); | 143 | return smallvec![attr]; |
143 | } | 144 | } |
144 | 145 | ||
145 | let subtree = match &attr.input { | 146 | let subtree = match &attr.input { |
146 | Some(AttrInput::TokenTree(it)) => it, | 147 | Some(AttrInput::TokenTree(it)) => it, |
147 | _ => return Some(attr), | 148 | _ => return smallvec![attr], |
148 | }; | 149 | }; |
149 | 150 | ||
150 | // Input subtree is: `(cfg, attr)` | 151 | // Input subtree is: `(cfg, $(attr),+)` |
151 | // Split it up into a `cfg` and an `attr` subtree. | 152 | // Split it up into a `cfg` subtree and the `attr` subtrees. |
152 | // FIXME: There should be a common API for this. | 153 | // FIXME: There should be a common API for this. |
153 | let mut saw_comma = false; | 154 | let mut parts = subtree.token_trees.split( |
154 | let (mut cfg, attr): (Vec<_>, Vec<_>) = | 155 | |tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ','), |
155 | subtree.clone().token_trees.into_iter().partition(|tree| { | 156 | ); |
156 | if saw_comma { | 157 | let cfg = parts.next().unwrap(); |
157 | return false; | 158 | let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() }; |
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); | 159 | let cfg = CfgExpr::parse(&cfg); |
160 | let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| { | ||
161 | let tree = Subtree { delimiter: None, token_trees: attr.to_vec() }; | ||
162 | let attr = ast::Attr::parse(&format!("#[{}]", tree)).ok()?; | ||
163 | let hygiene = Hygiene::new_unhygienic(); // FIXME | ||
164 | Attr::from_src(attr, &hygiene) | ||
165 | }); | ||
174 | 166 | ||
175 | let cfg_options = &crate_graph[krate].cfg_options; | 167 | let cfg_options = &crate_graph[krate].cfg_options; |
176 | if cfg_options.check(&cfg) == Some(false) { | 168 | if cfg_options.check(&cfg) == Some(false) { |
177 | None | 169 | smallvec![] |
178 | } else { | 170 | } else { |
179 | cov_mark::hit!(cfg_attr_active); | 171 | cov_mark::hit!(cfg_attr_active); |
180 | 172 | ||
181 | let attr = ast::Attr::parse(&format!("#[{}]", attr)).ok()?; | 173 | attrs.collect() |
182 | let hygiene = Hygiene::new_unhygienic(); // FIXME | ||
183 | Attr::from_src(attr, &hygiene) | ||
184 | } | 174 | } |
185 | }) | 175 | }) |
186 | .collect(); | 176 | .collect(); |
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 6bb334573..09bcb10dc 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -209,18 +209,6 @@ impl ItemTree { | |||
209 | } | 209 | } |
210 | } | 210 | } |
211 | 211 | ||
212 | pub fn source<S: ItemTreeNode>(&self, db: &dyn DefDatabase, of: ItemTreeId<S>) -> S::Source { | ||
213 | // This unwrap cannot fail, since it has either succeeded above, or resulted in an empty | ||
214 | // ItemTree (in which case there is no valid `FileItemTreeId` to call this method with). | ||
215 | let root = | ||
216 | db.parse_or_expand(of.file_id).expect("parse_or_expand failed on constructed ItemTree"); | ||
217 | |||
218 | let id = self[of.value].ast_id(); | ||
219 | let map = db.ast_id_map(of.file_id); | ||
220 | let ptr = map.get(id); | ||
221 | ptr.to_node(&root) | ||
222 | } | ||
223 | |||
224 | fn data(&self) -> &ItemTreeData { | 212 | fn data(&self) -> &ItemTreeData { |
225 | self.data.as_ref().expect("attempted to access data of empty ItemTree") | 213 | self.data.as_ref().expect("attempted to access data of empty ItemTree") |
226 | } | 214 | } |
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index 6d11c5be4..c6655c5fb 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -341,6 +341,16 @@ pub enum DefWithBodyId { | |||
341 | 341 | ||
342 | impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId); | 342 | impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId); |
343 | 343 | ||
344 | impl DefWithBodyId { | ||
345 | pub fn as_generic_def_id(self) -> Option<GenericDefId> { | ||
346 | match self { | ||
347 | DefWithBodyId::FunctionId(f) => Some(f.into()), | ||
348 | DefWithBodyId::StaticId(_) => None, | ||
349 | DefWithBodyId::ConstId(c) => Some(c.into()), | ||
350 | } | ||
351 | } | ||
352 | } | ||
353 | |||
344 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | 354 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] |
345 | pub enum AssocItemId { | 355 | pub enum AssocItemId { |
346 | FunctionId(FunctionId), | 356 | FunctionId(FunctionId), |
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs index d5ef8ceb5..1b8e885b0 100644 --- a/crates/hir_def/src/nameres/tests/diagnostics.rs +++ b/crates/hir_def/src/nameres/tests/diagnostics.rs | |||
@@ -149,6 +149,9 @@ fn inactive_via_cfg_attr() { | |||
149 | #[cfg_attr(not(never), cfg(not(no)))] fn f() {} | 149 | #[cfg_attr(not(never), cfg(not(no)))] fn f() {} |
150 | 150 | ||
151 | #[cfg_attr(never, cfg(no))] fn g() {} | 151 | #[cfg_attr(never, cfg(no))] fn g() {} |
152 | |||
153 | #[cfg_attr(not(never), inline, cfg(no))] fn h() {} | ||
154 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: no is disabled | ||
152 | "#, | 155 | "#, |
153 | ); | 156 | ); |
154 | } | 157 | } |
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs index eda982c85..10977761c 100644 --- a/crates/hir_def/src/test_db.rs +++ b/crates/hir_def/src/test_db.rs | |||
@@ -15,7 +15,7 @@ use rustc_hash::FxHashSet; | |||
15 | use syntax::{algo, ast, AstNode, TextRange, TextSize}; | 15 | use syntax::{algo, ast, AstNode, TextRange, TextSize}; |
16 | use test_utils::extract_annotations; | 16 | use test_utils::extract_annotations; |
17 | 17 | ||
18 | use crate::{db::DefDatabase, nameres::DefMap, Lookup, ModuleDefId, ModuleId}; | 18 | use crate::{db::DefDatabase, nameres::DefMap, src::HasSource, Lookup, ModuleDefId, ModuleId}; |
19 | 19 | ||
20 | #[salsa::database( | 20 | #[salsa::database( |
21 | base_db::SourceDatabaseExtStorage, | 21 | base_db::SourceDatabaseExtStorage, |
@@ -115,14 +115,9 @@ impl TestDB { | |||
115 | if file_id != position.file_id.into() { | 115 | if file_id != position.file_id.into() { |
116 | continue; | 116 | continue; |
117 | } | 117 | } |
118 | let root = self.parse_or_expand(file_id).unwrap(); | ||
119 | let ast_map = self.ast_id_map(file_id); | ||
120 | let item_tree = self.item_tree(file_id); | ||
121 | for decl in module.scope.declarations() { | 118 | for decl in module.scope.declarations() { |
122 | if let ModuleDefId::FunctionId(it) = decl { | 119 | if let ModuleDefId::FunctionId(it) = decl { |
123 | let ast = | 120 | let range = it.lookup(self).source(self).value.syntax().text_range(); |
124 | ast_map.get(item_tree[it.lookup(self).id.value].ast_id).to_node(&root); | ||
125 | let range = ast.syntax().text_range(); | ||
126 | 121 | ||
127 | if !range.contains(position.offset) { | 122 | if !range.contains(position.offset) { |
128 | continue; | 123 | continue; |