aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/body.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/body.rs')
-rw-r--r--crates/hir_def/src/body.rs69
1 files changed, 25 insertions, 44 deletions
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs
index 9a9a605dd..d10b1af01 100644
--- a/crates/hir_def/src/body.rs
+++ b/crates/hir_def/src/body.rs
@@ -1,6 +1,9 @@
1//! Defines `Body`: a lowered representation of bodies of functions, statics and 1//! Defines `Body`: a lowered representation of bodies of functions, statics and
2//! consts. 2//! consts.
3mod lower; 3mod lower;
4mod diagnostics;
5#[cfg(test)]
6mod tests;
4pub mod scope; 7pub mod scope;
5 8
6use std::{mem, ops::Index, sync::Arc}; 9use std::{mem, ops::Index, sync::Arc};
@@ -10,7 +13,10 @@ use base_db::CrateId;
10use cfg::CfgOptions; 13use cfg::CfgOptions;
11use drop_bomb::DropBomb; 14use drop_bomb::DropBomb;
12use either::Either; 15use either::Either;
13use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroDefId}; 16use hir_expand::{
17 ast_id_map::AstIdMap, diagnostics::DiagnosticSink, hygiene::Hygiene, AstId, HirFileId, InFile,
18 MacroDefId,
19};
14use rustc_hash::FxHashMap; 20use rustc_hash::FxHashMap;
15use syntax::{ast, AstNode, AstPtr}; 21use syntax::{ast, AstNode, AstPtr};
16use test_utils::mark; 22use test_utils::mark;
@@ -105,14 +111,16 @@ impl Expander {
105 111
106 let macro_call = InFile::new(self.current_file_id, &macro_call); 112 let macro_call = InFile::new(self.current_file_id, &macro_call);
107 113
108 if let Some(call_id) = macro_call.as_call_id(db, self.crate_def_map.krate, |path| { 114 let resolver = |path: ModPath| -> Option<MacroDefId> {
109 if let Some(local_scope) = local_scope { 115 if let Some(local_scope) = local_scope {
110 if let Some(def) = path.as_ident().and_then(|n| local_scope.get_legacy_macro(n)) { 116 if let Some(def) = path.as_ident().and_then(|n| local_scope.get_legacy_macro(n)) {
111 return Some(def); 117 return Some(def);
112 } 118 }
113 } 119 }
114 self.resolve_path_as_macro(db, &path) 120 self.resolve_path_as_macro(db, &path)
115 }) { 121 };
122
123 if let Some(call_id) = macro_call.as_call_id(db, self.crate_def_map.krate, resolver) {
116 let file_id = call_id.as_file(); 124 let file_id = call_id.as_file();
117 if let Some(node) = db.parse_or_expand(file_id) { 125 if let Some(node) = db.parse_or_expand(file_id) {
118 if let Some(expr) = T::cast(node) { 126 if let Some(expr) = T::cast(node) {
@@ -148,8 +156,12 @@ impl Expander {
148 InFile { file_id: self.current_file_id, value } 156 InFile { file_id: self.current_file_id, value }
149 } 157 }
150 158
151 pub(crate) fn is_cfg_enabled(&self, owner: &dyn ast::AttrsOwner) -> bool { 159 pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs {
152 self.cfg_expander.is_cfg_enabled(owner) 160 self.cfg_expander.parse_attrs(owner)
161 }
162
163 pub(crate) fn cfg_options(&self) -> &CfgOptions {
164 &self.cfg_expander.cfg_options
153 } 165 }
154 166
155 fn parse_path(&mut self, path: ast::Path) -> Option<Path> { 167 fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
@@ -217,6 +229,10 @@ pub struct BodySourceMap {
217 pat_map_back: ArenaMap<PatId, Result<PatSource, SyntheticSyntax>>, 229 pat_map_back: ArenaMap<PatId, Result<PatSource, SyntheticSyntax>>,
218 field_map: FxHashMap<(ExprId, usize), InFile<AstPtr<ast::RecordExprField>>>, 230 field_map: FxHashMap<(ExprId, usize), InFile<AstPtr<ast::RecordExprField>>>,
219 expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>, 231 expansions: FxHashMap<InFile<AstPtr<ast::MacroCall>>, HirFileId>,
232
233 /// Diagnostics accumulated during body lowering. These contain `AstPtr`s and so are stored in
234 /// the source map (since they're just as volatile).
235 diagnostics: Vec<diagnostics::BodyDiagnostic>,
220} 236}
221 237
222#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)] 238#[derive(Default, Debug, Eq, PartialEq, Clone, Copy)]
@@ -316,45 +332,10 @@ impl BodySourceMap {
316 pub fn field_syntax(&self, expr: ExprId, field: usize) -> InFile<AstPtr<ast::RecordExprField>> { 332 pub fn field_syntax(&self, expr: ExprId, field: usize) -> InFile<AstPtr<ast::RecordExprField>> {
317 self.field_map[&(expr, field)].clone() 333 self.field_map[&(expr, field)].clone()
318 } 334 }
319}
320 335
321#[cfg(test)] 336 pub(crate) fn add_diagnostics(&self, _db: &dyn DefDatabase, sink: &mut DiagnosticSink<'_>) {
322mod tests { 337 for diag in &self.diagnostics {
323 use base_db::{fixture::WithFixture, SourceDatabase}; 338 diag.add_to(sink);
324 use test_utils::mark; 339 }
325
326 use crate::ModuleDefId;
327
328 use super::*;
329
330 fn lower(ra_fixture: &str) -> Arc<Body> {
331 let (db, file_id) = crate::test_db::TestDB::with_single_file(ra_fixture);
332
333 let krate = db.crate_graph().iter().next().unwrap();
334 let def_map = db.crate_def_map(krate);
335 let module = def_map.modules_for_file(file_id).next().unwrap();
336 let module = &def_map[module];
337 let fn_def = match module.scope.declarations().next().unwrap() {
338 ModuleDefId::FunctionId(it) => it,
339 _ => panic!(),
340 };
341
342 db.body(fn_def.into())
343 }
344
345 #[test]
346 fn your_stack_belongs_to_me() {
347 mark::check!(your_stack_belongs_to_me);
348 lower(
349 "
350macro_rules! n_nuple {
351 ($e:tt) => ();
352 ($($rest:tt)*) => {{
353 (n_nuple!($($rest)*)None,)
354 }};
355}
356fn main() { n_nuple!(1,2,3); }
357",
358 );
359 } 340 }
360} 341}