diff options
Diffstat (limited to 'crates/hir_def')
-rw-r--r-- | crates/hir_def/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/hir_def/src/attr.rs | 48 | ||||
-rw-r--r-- | crates/hir_def/src/body.rs | 19 | ||||
-rw-r--r-- | crates/hir_def/src/body/lower.rs | 24 | ||||
-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 |
8 files changed, 60 insertions, 67 deletions
diff --git a/crates/hir_def/Cargo.toml b/crates/hir_def/Cargo.toml index c2d99280f..475d337f3 100644 --- a/crates/hir_def/Cargo.toml +++ b/crates/hir_def/Cargo.toml | |||
@@ -10,7 +10,7 @@ edition = "2018" | |||
10 | doctest = false | 10 | doctest = false |
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | cov-mark = "1.1" | 13 | cov-mark = { version = "1.1", features = ["thread-local"] } |
14 | log = "0.4.8" | 14 | log = "0.4.8" |
15 | once_cell = "1.3.1" | 15 | once_cell = "1.3.1" |
16 | rustc-hash = "1.1.0" | 16 | rustc-hash = "1.1.0" |
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/body.rs b/crates/hir_def/src/body.rs index 19c4eb521..8bcc350ce 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs | |||
@@ -253,11 +253,18 @@ pub type LabelSource = InFile<LabelPtr>; | |||
253 | pub struct BodySourceMap { | 253 | pub struct BodySourceMap { |
254 | expr_map: FxHashMap<ExprSource, ExprId>, | 254 | expr_map: FxHashMap<ExprSource, ExprId>, |
255 | expr_map_back: ArenaMap<ExprId, Result<ExprSource, SyntheticSyntax>>, | 255 | expr_map_back: ArenaMap<ExprId, Result<ExprSource, SyntheticSyntax>>, |
256 | |||
256 | pat_map: FxHashMap<PatSource, PatId>, | 257 | pat_map: FxHashMap<PatSource, PatId>, |
257 | pat_map_back: ArenaMap<PatId, Result<PatSource, SyntheticSyntax>>, | 258 | pat_map_back: ArenaMap<PatId, Result<PatSource, SyntheticSyntax>>, |
259 | |||
258 | label_map: FxHashMap<LabelSource, LabelId>, | 260 | label_map: FxHashMap<LabelSource, LabelId>, |
259 | label_map_back: ArenaMap<LabelId, LabelSource>, | 261 | label_map_back: ArenaMap<LabelId, LabelSource>, |
260 | field_map: FxHashMap<(ExprId, usize), InFile<AstPtr<ast::RecordExprField>>>, | 262 | |
263 | /// We don't create explicit nodes for record fields (`S { record_field: 92 }`). | ||
264 | /// Instead, we use id of expression (`92`) to identify the field. | ||
265 | field_map: FxHashMap<InFile<AstPtr<ast::RecordExprField>>, ExprId>, | ||
266 | field_map_back: FxHashMap<ExprId, InFile<AstPtr<ast::RecordExprField>>>, | ||
267 | |||
261 | expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>, | 268 | expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>, |
262 | 269 | ||
263 | /// Diagnostics accumulated during body lowering. These contain `AstPtr`s and so are stored in | 270 | /// Diagnostics accumulated during body lowering. These contain `AstPtr`s and so are stored in |
@@ -337,6 +344,8 @@ impl Index<LabelId> for Body { | |||
337 | } | 344 | } |
338 | } | 345 | } |
339 | 346 | ||
347 | // FIXME: Change `node_` prefix to something more reasonable. | ||
348 | // Perhaps `expr_syntax` and `expr_id`? | ||
340 | impl BodySourceMap { | 349 | impl BodySourceMap { |
341 | pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> { | 350 | pub fn expr_syntax(&self, expr: ExprId) -> Result<ExprSource, SyntheticSyntax> { |
342 | self.expr_map_back[expr].clone() | 351 | self.expr_map_back[expr].clone() |
@@ -375,8 +384,12 @@ impl BodySourceMap { | |||
375 | self.label_map.get(&src).cloned() | 384 | self.label_map.get(&src).cloned() |
376 | } | 385 | } |
377 | 386 | ||
378 | pub fn field_syntax(&self, expr: ExprId, field: usize) -> InFile<AstPtr<ast::RecordExprField>> { | 387 | pub fn field_syntax(&self, expr: ExprId) -> InFile<AstPtr<ast::RecordExprField>> { |
379 | self.field_map[&(expr, field)].clone() | 388 | self.field_map_back[&expr].clone() |
389 | } | ||
390 | pub fn node_field(&self, node: InFile<&ast::RecordExprField>) -> Option<ExprId> { | ||
391 | let src = node.map(|it| AstPtr::new(it)); | ||
392 | self.field_map.get(&src).cloned() | ||
380 | } | 393 | } |
381 | 394 | ||
382 | pub(crate) fn add_diagnostics(&self, _db: &dyn DefDatabase, sink: &mut DiagnosticSink<'_>) { | 395 | pub(crate) fn add_diagnostics(&self, _db: &dyn DefDatabase, sink: &mut DiagnosticSink<'_>) { |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 8c8eb8007..8934ae6c9 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -379,23 +379,22 @@ impl ExprCollector<'_> { | |||
379 | } | 379 | } |
380 | ast::Expr::RecordExpr(e) => { | 380 | ast::Expr::RecordExpr(e) => { |
381 | let path = e.path().and_then(|path| self.expander.parse_path(path)); | 381 | let path = e.path().and_then(|path| self.expander.parse_path(path)); |
382 | let mut field_ptrs = Vec::new(); | ||
383 | let record_lit = if let Some(nfl) = e.record_expr_field_list() { | 382 | let record_lit = if let Some(nfl) = e.record_expr_field_list() { |
384 | let fields = nfl | 383 | let fields = nfl |
385 | .fields() | 384 | .fields() |
386 | .inspect(|field| field_ptrs.push(AstPtr::new(field))) | ||
387 | .filter_map(|field| { | 385 | .filter_map(|field| { |
388 | self.check_cfg(&field)?; | 386 | self.check_cfg(&field)?; |
389 | 387 | ||
390 | let name = field.field_name()?.as_name(); | 388 | let name = field.field_name()?.as_name(); |
391 | 389 | ||
392 | Some(RecordLitField { | 390 | let expr = match field.expr() { |
393 | name, | 391 | Some(e) => self.collect_expr(e), |
394 | expr: match field.expr() { | 392 | None => self.missing_expr(), |
395 | Some(e) => self.collect_expr(e), | 393 | }; |
396 | None => self.missing_expr(), | 394 | let src = self.expander.to_source(AstPtr::new(&field)); |
397 | }, | 395 | self.source_map.field_map.insert(src.clone(), expr); |
398 | }) | 396 | self.source_map.field_map_back.insert(expr, src); |
397 | Some(RecordLitField { name, expr }) | ||
399 | }) | 398 | }) |
400 | .collect(); | 399 | .collect(); |
401 | let spread = nfl.spread().map(|s| self.collect_expr(s)); | 400 | let spread = nfl.spread().map(|s| self.collect_expr(s)); |
@@ -404,12 +403,7 @@ impl ExprCollector<'_> { | |||
404 | Expr::RecordLit { path, fields: Vec::new(), spread: None } | 403 | Expr::RecordLit { path, fields: Vec::new(), spread: None } |
405 | }; | 404 | }; |
406 | 405 | ||
407 | let res = self.alloc_expr(record_lit, syntax_ptr); | 406 | self.alloc_expr(record_lit, syntax_ptr) |
408 | for (i, ptr) in field_ptrs.into_iter().enumerate() { | ||
409 | let src = self.expander.to_source(ptr); | ||
410 | self.source_map.field_map.insert((res, i), src); | ||
411 | } | ||
412 | res | ||
413 | } | 407 | } |
414 | ast::Expr::FieldExpr(e) => { | 408 | ast::Expr::FieldExpr(e) => { |
415 | let expr = self.collect_expr_opt(e.expr()); | 409 | let expr = self.collect_expr_opt(e.expr()); |
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 bfc1ab13f..c22ef46fd 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; |