aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src/body.rs
diff options
context:
space:
mode:
authorSeivan Heidari <[email protected]>2019-12-23 14:35:31 +0000
committerSeivan Heidari <[email protected]>2019-12-23 14:35:31 +0000
commitb21d9337d9200e2cfdc90b386591c72c302dc03e (patch)
treef81f5c08f821115cee26fa4d3ceaae88c7807fd5 /crates/ra_hir_def/src/body.rs
parent18a0937585b836ec5ed054b9ae48e0156ab6d9ef (diff)
parentce07a2daa9e53aa86a769f8641b14c2878444fbc (diff)
Merge branch 'master' into feature/themes
Diffstat (limited to 'crates/ra_hir_def/src/body.rs')
-rw-r--r--crates/ra_hir_def/src/body.rs108
1 files changed, 70 insertions, 38 deletions
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index a57a0176d..d3e4c50ae 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -3,58 +3,75 @@
3mod lower; 3mod lower;
4pub mod scope; 4pub mod scope;
5 5
6use std::{ops::Index, sync::Arc}; 6use std::{mem, ops::Index, sync::Arc};
7 7
8use drop_bomb::DropBomb;
9use either::Either;
8use hir_expand::{ 10use hir_expand::{
9 either::Either, hygiene::Hygiene, AstId, HirFileId, MacroDefId, MacroFileKind, Source, 11 ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId,
10}; 12};
11use ra_arena::{map::ArenaMap, Arena}; 13use ra_arena::{map::ArenaMap, Arena};
14use ra_prof::profile;
12use ra_syntax::{ast, AstNode, AstPtr}; 15use ra_syntax::{ast, AstNode, AstPtr};
13use rustc_hash::FxHashMap; 16use rustc_hash::FxHashMap;
14 17
15use crate::{ 18use crate::{
16 db::DefDatabase, 19 db::DefDatabase,
17 expr::{Expr, ExprId, Pat, PatId}, 20 expr::{Expr, ExprId, Pat, PatId},
21 item_scope::BuiltinShadowMode,
22 item_scope::ItemScope,
18 nameres::CrateDefMap, 23 nameres::CrateDefMap,
19 path::Path, 24 path::{ModPath, Path},
20 DefWithBodyId, HasModule, HasSource, Lookup, ModuleId, 25 src::HasSource,
26 DefWithBodyId, HasModule, Lookup, ModuleId,
21}; 27};
22 28
23struct Expander { 29pub(crate) struct Expander {
24 crate_def_map: Arc<CrateDefMap>, 30 crate_def_map: Arc<CrateDefMap>,
25 current_file_id: HirFileId, 31 current_file_id: HirFileId,
26 hygiene: Hygiene, 32 hygiene: Hygiene,
33 ast_id_map: Arc<AstIdMap>,
27 module: ModuleId, 34 module: ModuleId,
28} 35}
29 36
30impl Expander { 37impl Expander {
31 fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander { 38 pub(crate) fn new(
39 db: &impl DefDatabase,
40 current_file_id: HirFileId,
41 module: ModuleId,
42 ) -> Expander {
32 let crate_def_map = db.crate_def_map(module.krate); 43 let crate_def_map = db.crate_def_map(module.krate);
33 let hygiene = Hygiene::new(db, current_file_id); 44 let hygiene = Hygiene::new(db, current_file_id);
34 Expander { crate_def_map, current_file_id, hygiene, module } 45 let ast_id_map = db.ast_id_map(current_file_id);
46 Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module }
35 } 47 }
36 48
37 fn enter_expand( 49 pub(crate) fn enter_expand<T: ast::AstNode, DB: DefDatabase>(
38 &mut self, 50 &mut self,
39 db: &impl DefDatabase, 51 db: &DB,
40 macro_call: ast::MacroCall, 52 macro_call: ast::MacroCall,
41 ) -> Option<(Mark, ast::Expr)> { 53 ) -> Option<(Mark, T)> {
42 let ast_id = AstId::new( 54 let ast_id = AstId::new(
43 self.current_file_id, 55 self.current_file_id,
44 db.ast_id_map(self.current_file_id).ast_id(&macro_call), 56 db.ast_id_map(self.current_file_id).ast_id(&macro_call),
45 ); 57 );
46 58
47 if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) { 59 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) { 60 if let Some(def) = self.resolve_path_as_macro(db, &path) {
49 let call_id = def.as_call_id(db, ast_id); 61 let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id));
50 let file_id = call_id.as_file(MacroFileKind::Expr); 62 let file_id = call_id.as_file();
51 if let Some(node) = db.parse_or_expand(file_id) { 63 if let Some(node) = db.parse_or_expand(file_id) {
52 if let Some(expr) = ast::Expr::cast(node) { 64 if let Some(expr) = T::cast(node) {
53 log::debug!("macro expansion {:#?}", expr.syntax()); 65 log::debug!("macro expansion {:#?}", expr.syntax());
54 66
55 let mark = Mark { file_id: self.current_file_id }; 67 let mark = Mark {
68 file_id: self.current_file_id,
69 ast_id_map: mem::take(&mut self.ast_id_map),
70 bomb: DropBomb::new("expansion mark dropped"),
71 };
56 self.hygiene = Hygiene::new(db, file_id); 72 self.hygiene = Hygiene::new(db, file_id);
57 self.current_file_id = file_id; 73 self.current_file_id = file_id;
74 self.ast_id_map = db.ast_id_map(file_id);
58 75
59 return Some((mark, expr)); 76 return Some((mark, expr));
60 } 77 }
@@ -67,37 +84,44 @@ impl Expander {
67 None 84 None
68 } 85 }
69 86
70 fn exit(&mut self, db: &impl DefDatabase, mark: Mark) { 87 pub(crate) fn exit(&mut self, db: &impl DefDatabase, mut mark: Mark) {
71 self.hygiene = Hygiene::new(db, mark.file_id); 88 self.hygiene = Hygiene::new(db, mark.file_id);
72 self.current_file_id = mark.file_id; 89 self.current_file_id = mark.file_id;
73 std::mem::forget(mark); 90 self.ast_id_map = mem::take(&mut mark.ast_id_map);
91 mark.bomb.defuse();
74 } 92 }
75 93
76 fn to_source<T>(&self, value: T) -> Source<T> { 94 pub(crate) fn to_source<T>(&self, value: T) -> InFile<T> {
77 Source { file_id: self.current_file_id, value } 95 InFile { file_id: self.current_file_id, value }
78 } 96 }
79 97
80 fn parse_path(&mut self, path: ast::Path) -> Option<Path> { 98 fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
81 Path::from_src(path, &self.hygiene) 99 Path::from_src(path, &self.hygiene)
82 } 100 }
83 101
84 fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option<MacroDefId> { 102 fn parse_mod_path(&mut self, path: ast::Path) -> Option<ModPath> {
85 self.crate_def_map.resolve_path(db, self.module.local_id, path).0.take_macros() 103 ModPath::from_src(path, &self.hygiene)
86 } 104 }
87}
88 105
89struct Mark { 106 fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &ModPath) -> Option<MacroDefId> {
90 file_id: HirFileId, 107 self.crate_def_map
91} 108 .resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other)
109 .0
110 .take_macros()
111 }
92 112
93impl Drop for Mark { 113 fn ast_id<N: AstNode>(&self, item: &N) -> AstId<N> {
94 fn drop(&mut self) { 114 let file_local_id = self.ast_id_map.ast_id(item);
95 if !std::thread::panicking() { 115 AstId::new(self.current_file_id, file_local_id)
96 panic!("dropped mark")
97 }
98 } 116 }
99} 117}
100 118
119pub(crate) struct Mark {
120 file_id: HirFileId,
121 ast_id_map: Arc<AstIdMap>,
122 bomb: DropBomb,
123}
124
101/// The body of an item (function, const etc.). 125/// The body of an item (function, const etc.).
102#[derive(Debug, Eq, PartialEq)] 126#[derive(Debug, Eq, PartialEq)]
103pub struct Body { 127pub struct Body {
@@ -112,13 +136,14 @@ pub struct Body {
112 pub params: Vec<PatId>, 136 pub params: Vec<PatId>,
113 /// The `ExprId` of the actual body expression. 137 /// The `ExprId` of the actual body expression.
114 pub body_expr: ExprId, 138 pub body_expr: ExprId,
139 pub item_scope: ItemScope,
115} 140}
116 141
117pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>; 142pub type ExprPtr = Either<AstPtr<ast::Expr>, AstPtr<ast::RecordField>>;
118pub type ExprSource = Source<ExprPtr>; 143pub type ExprSource = InFile<ExprPtr>;
119 144
120pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>; 145pub type PatPtr = Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>;
121pub type PatSource = Source<PatPtr>; 146pub type PatSource = InFile<PatPtr>;
122 147
123/// An item body together with the mapping from syntax nodes to HIR expression 148/// An item body together with the mapping from syntax nodes to HIR expression
124/// IDs. This is needed to go from e.g. a position in a file to the HIR 149/// IDs. This is needed to go from e.g. a position in a file to the HIR
@@ -145,6 +170,7 @@ impl Body {
145 db: &impl DefDatabase, 170 db: &impl DefDatabase,
146 def: DefWithBodyId, 171 def: DefWithBodyId,
147 ) -> (Arc<Body>, Arc<BodySourceMap>) { 172 ) -> (Arc<Body>, Arc<BodySourceMap>) {
173 let _p = profile("body_with_source_map_query");
148 let mut params = None; 174 let mut params = None;
149 175
150 let (file_id, module, body) = match def { 176 let (file_id, module, body) = match def {
@@ -166,7 +192,7 @@ impl Body {
166 } 192 }
167 }; 193 };
168 let expander = Expander::new(db, file_id, module); 194 let expander = Expander::new(db, file_id, module);
169 let (body, source_map) = Body::new(db, expander, params, body); 195 let (body, source_map) = Body::new(db, def, expander, params, body);
170 (Arc::new(body), Arc::new(source_map)) 196 (Arc::new(body), Arc::new(source_map))
171 } 197 }
172 198
@@ -176,11 +202,12 @@ impl Body {
176 202
177 fn new( 203 fn new(
178 db: &impl DefDatabase, 204 db: &impl DefDatabase,
205 def: DefWithBodyId,
179 expander: Expander, 206 expander: Expander,
180 params: Option<ast::ParamList>, 207 params: Option<ast::ParamList>,
181 body: Option<ast::Expr>, 208 body: Option<ast::Expr>,
182 ) -> (Body, BodySourceMap) { 209 ) -> (Body, BodySourceMap) {
183 lower::lower(db, expander, params, body) 210 lower::lower(db, def, expander, params, body)
184 } 211 }
185} 212}
186 213
@@ -205,8 +232,13 @@ impl BodySourceMap {
205 self.expr_map_back.get(expr).copied() 232 self.expr_map_back.get(expr).copied()
206 } 233 }
207 234
208 pub fn node_expr(&self, node: Source<&ast::Expr>) -> Option<ExprId> { 235 pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option<ExprId> {
209 let src = node.map(|it| Either::A(AstPtr::new(it))); 236 let src = node.map(|it| Either::Left(AstPtr::new(it)));
237 self.expr_map.get(&src).cloned()
238 }
239
240 pub fn field_init_shorthand_expr(&self, node: InFile<&ast::RecordField>) -> Option<ExprId> {
241 let src = node.map(|it| Either::Right(AstPtr::new(it)));
210 self.expr_map.get(&src).cloned() 242 self.expr_map.get(&src).cloned()
211 } 243 }
212 244
@@ -214,8 +246,8 @@ impl BodySourceMap {
214 self.pat_map_back.get(pat).copied() 246 self.pat_map_back.get(pat).copied()
215 } 247 }
216 248
217 pub fn node_pat(&self, node: Source<&ast::Pat>) -> Option<PatId> { 249 pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option<PatId> {
218 let src = node.map(|it| Either::A(AstPtr::new(it))); 250 let src = node.map(|it| Either::Left(AstPtr::new(it)));
219 self.pat_map.get(&src).cloned() 251 self.pat_map.get(&src).cloned()
220 } 252 }
221 253