diff options
Diffstat (limited to 'crates/ra_hir_def/src/body.rs')
-rw-r--r-- | crates/ra_hir_def/src/body.rs | 63 |
1 files changed, 42 insertions, 21 deletions
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 7787cb87f..401fe0b9b 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -3,10 +3,13 @@ | |||
3 | mod lower; | 3 | mod lower; |
4 | pub mod scope; | 4 | pub mod scope; |
5 | 5 | ||
6 | use std::{ops::Index, sync::Arc}; | 6 | use std::{mem, ops::Index, sync::Arc}; |
7 | 7 | ||
8 | use drop_bomb::DropBomb; | ||
8 | use either::Either; | 9 | use either::Either; |
9 | use hir_expand::{hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId}; | 10 | use hir_expand::{ |
11 | ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId, | ||
12 | }; | ||
10 | use ra_arena::{map::ArenaMap, Arena}; | 13 | use ra_arena::{map::ArenaMap, Arena}; |
11 | use ra_syntax::{ast, AstNode, AstPtr}; | 14 | use ra_syntax::{ast, AstNode, AstPtr}; |
12 | use rustc_hash::FxHashMap; | 15 | use rustc_hash::FxHashMap; |
@@ -15,15 +18,16 @@ use crate::{ | |||
15 | db::DefDatabase, | 18 | db::DefDatabase, |
16 | expr::{Expr, ExprId, Pat, PatId}, | 19 | expr::{Expr, ExprId, Pat, PatId}, |
17 | nameres::{BuiltinShadowMode, CrateDefMap}, | 20 | nameres::{BuiltinShadowMode, CrateDefMap}, |
18 | path::Path, | 21 | path::{ModPath, Path}, |
19 | src::HasSource, | 22 | src::HasSource, |
20 | DefWithBodyId, HasModule, Lookup, ModuleId, | 23 | DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId, |
21 | }; | 24 | }; |
22 | 25 | ||
23 | struct Expander { | 26 | struct Expander { |
24 | crate_def_map: Arc<CrateDefMap>, | 27 | crate_def_map: Arc<CrateDefMap>, |
25 | current_file_id: HirFileId, | 28 | current_file_id: HirFileId, |
26 | hygiene: Hygiene, | 29 | hygiene: Hygiene, |
30 | ast_id_map: Arc<AstIdMap>, | ||
27 | module: ModuleId, | 31 | module: ModuleId, |
28 | } | 32 | } |
29 | 33 | ||
@@ -31,7 +35,8 @@ impl Expander { | |||
31 | fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander { | 35 | fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander { |
32 | let crate_def_map = db.crate_def_map(module.krate); | 36 | let crate_def_map = db.crate_def_map(module.krate); |
33 | let hygiene = Hygiene::new(db, current_file_id); | 37 | let hygiene = Hygiene::new(db, current_file_id); |
34 | Expander { crate_def_map, current_file_id, hygiene, module } | 38 | let ast_id_map = db.ast_id_map(current_file_id); |
39 | Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module } | ||
35 | } | 40 | } |
36 | 41 | ||
37 | fn enter_expand( | 42 | fn enter_expand( |
@@ -44,7 +49,7 @@ impl Expander { | |||
44 | db.ast_id_map(self.current_file_id).ast_id(¯o_call), | 49 | db.ast_id_map(self.current_file_id).ast_id(¯o_call), |
45 | ); | 50 | ); |
46 | 51 | ||
47 | if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) { | 52 | if let Some(path) = macro_call.path().and_then(|path| self.parse_mod_path(path)) { |
48 | if let Some(def) = self.resolve_path_as_macro(db, &path) { | 53 | if let Some(def) = self.resolve_path_as_macro(db, &path) { |
49 | let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id)); | 54 | let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id)); |
50 | let file_id = call_id.as_file(); | 55 | let file_id = call_id.as_file(); |
@@ -52,9 +57,14 @@ impl Expander { | |||
52 | if let Some(expr) = ast::Expr::cast(node) { | 57 | if let Some(expr) = ast::Expr::cast(node) { |
53 | log::debug!("macro expansion {:#?}", expr.syntax()); | 58 | log::debug!("macro expansion {:#?}", expr.syntax()); |
54 | 59 | ||
55 | let mark = Mark { file_id: self.current_file_id }; | 60 | let mark = Mark { |
61 | file_id: self.current_file_id, | ||
62 | ast_id_map: mem::take(&mut self.ast_id_map), | ||
63 | bomb: DropBomb::new("expansion mark dropped"), | ||
64 | }; | ||
56 | self.hygiene = Hygiene::new(db, file_id); | 65 | self.hygiene = Hygiene::new(db, file_id); |
57 | self.current_file_id = file_id; | 66 | self.current_file_id = file_id; |
67 | self.ast_id_map = db.ast_id_map(file_id); | ||
58 | 68 | ||
59 | return Some((mark, expr)); | 69 | return Some((mark, expr)); |
60 | } | 70 | } |
@@ -67,10 +77,11 @@ impl Expander { | |||
67 | None | 77 | None |
68 | } | 78 | } |
69 | 79 | ||
70 | fn exit(&mut self, db: &impl DefDatabase, mark: Mark) { | 80 | fn exit(&mut self, db: &impl DefDatabase, mut mark: Mark) { |
71 | self.hygiene = Hygiene::new(db, mark.file_id); | 81 | self.hygiene = Hygiene::new(db, mark.file_id); |
72 | self.current_file_id = mark.file_id; | 82 | self.current_file_id = mark.file_id; |
73 | std::mem::forget(mark); | 83 | self.ast_id_map = mem::take(&mut mark.ast_id_map); |
84 | mark.bomb.defuse(); | ||
74 | } | 85 | } |
75 | 86 | ||
76 | fn to_source<T>(&self, value: T) -> InFile<T> { | 87 | fn to_source<T>(&self, value: T) -> InFile<T> { |
@@ -81,24 +92,27 @@ impl Expander { | |||
81 | Path::from_src(path, &self.hygiene) | 92 | Path::from_src(path, &self.hygiene) |
82 | } | 93 | } |
83 | 94 | ||
84 | fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> { | 95 | fn parse_mod_path(&mut self, path: ast::Path) -> Option<ModPath> { |
96 | ModPath::from_src(path, &self.hygiene) | ||
97 | } | ||
98 | |||
99 | fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &ModPath) -> Option<MacroDefId> { | ||
85 | self.crate_def_map | 100 | self.crate_def_map |
86 | .resolve_path(db, self.module.local_id, path.mod_path(), BuiltinShadowMode::Other) | 101 | .resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other) |
87 | .0 | 102 | .0 |
88 | .take_macros() | 103 | .take_macros() |
89 | } | 104 | } |
105 | |||
106 | fn ast_id<N: AstNode>(&self, item: &N) -> AstId<N> { | ||
107 | let file_local_id = self.ast_id_map.ast_id(item); | ||
108 | AstId::new(self.current_file_id, file_local_id) | ||
109 | } | ||
90 | } | 110 | } |
91 | 111 | ||
92 | struct Mark { | 112 | struct Mark { |
93 | file_id: HirFileId, | 113 | file_id: HirFileId, |
94 | } | 114 | ast_id_map: Arc<AstIdMap>, |
95 | 115 | bomb: DropBomb, | |
96 | impl Drop for Mark { | ||
97 | fn drop(&mut self) { | ||
98 | if !std::thread::panicking() { | ||
99 | panic!("dropped mark") | ||
100 | } | ||
101 | } | ||
102 | } | 116 | } |
103 | 117 | ||
104 | /// The body of an item (function, const etc.). | 118 | /// The body of an item (function, const etc.). |
@@ -115,6 +129,7 @@ pub struct Body { | |||
115 | pub params: Vec<PatId>, | 129 | pub params: Vec<PatId>, |
116 | /// The `ExprId` of the actual body expression. | 130 | /// The `ExprId` of the actual body expression. |
117 | pub body_expr: ExprId, | 131 | pub body_expr: ExprId, |
132 | pub defs: Vec<ModuleDefId>, | ||
118 | } | 133 | } |
119 | 134 | ||
120 | pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>; | 135 | pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>; |
@@ -169,7 +184,7 @@ impl Body { | |||
169 | } | 184 | } |
170 | }; | 185 | }; |
171 | let expander = Expander::new(db, file_id, module); | 186 | let expander = Expander::new(db, file_id, module); |
172 | let (body, source_map) = Body::new(db, expander, params, body); | 187 | let (body, source_map) = Body::new(db, def, expander, params, body); |
173 | (Arc::new(body), Arc::new(source_map)) | 188 | (Arc::new(body), Arc::new(source_map)) |
174 | } | 189 | } |
175 | 190 | ||
@@ -179,11 +194,12 @@ impl Body { | |||
179 | 194 | ||
180 | fn new( | 195 | fn new( |
181 | db: &impl DefDatabase, | 196 | db: &impl DefDatabase, |
197 | def: DefWithBodyId, | ||
182 | expander: Expander, | 198 | expander: Expander, |
183 | params: Option<ast::ParamList>, | 199 | params: Option<ast::ParamList>, |
184 | body: Option<ast::Expr>, | 200 | body: Option<ast::Expr>, |
185 | ) -> (Body, BodySourceMap) { | 201 | ) -> (Body, BodySourceMap) { |
186 | lower::lower(db, expander, params, body) | 202 | lower::lower(db, def, expander, params, body) |
187 | } | 203 | } |
188 | } | 204 | } |
189 | 205 | ||
@@ -213,6 +229,11 @@ impl BodySourceMap { | |||
213 | self.expr_map.get(&src).cloned() | 229 | self.expr_map.get(&src).cloned() |
214 | } | 230 | } |
215 | 231 | ||
232 | pub fn field_init_shorthand_expr(&self, node: InFile<&ast::RecordField>) -> Option<ExprId> { | ||
233 | let src = node.map(|it| Either::Right(AstPtr::new(it))); | ||
234 | self.expr_map.get(&src).cloned() | ||
235 | } | ||
236 | |||
216 | pub fn pat_syntax(&self, pat: PatId) -> Option<PatSource> { | 237 | pub fn pat_syntax(&self, pat: PatId) -> Option<PatSource> { |
217 | self.pat_map_back.get(pat).copied() | 238 | self.pat_map_back.get(pat).copied() |
218 | } | 239 | } |