aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-11-14 07:36:47 +0000
committerGitHub <[email protected]>2019-11-14 07:36:47 +0000
commit8af85263f7cd249356382aa61b98094594165364 (patch)
treebed1d8bfef7cd3c42917d30fae2d8002dd00c38c /crates
parent38a3c76d154231ded00ca1decfd55bdaebe67bae (diff)
parentda2ca01ebaaaaa47aa09c5848c53b145a68af8fa (diff)
Merge #2235
2235: Handle macro-generated expressions slightly less wrong r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/expr.rs4
-rw-r--r--crates/ra_hir/src/expr/scope.rs6
-rw-r--r--crates/ra_hir/src/from_source.rs3
-rw-r--r--crates/ra_hir/src/source_binder.rs44
-rw-r--r--crates/ra_hir_def/src/body.rs104
-rw-r--r--crates/ra_hir_def/src/body/lower.rs90
-rw-r--r--crates/ra_hir_expand/src/lib.rs5
7 files changed, 156 insertions, 100 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 82955fa55..d19f5d14c 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -40,8 +40,8 @@ pub(crate) fn body_with_source_map_query(
40 (src.file_id, src.ast.body()) 40 (src.file_id, src.ast.body())
41 } 41 }
42 }; 42 };
43 let resolver = hir_def::body::MacroResolver::new(db, def.module(db).id); 43 let expander = hir_def::body::Expander::new(db, file_id, def.module(db).id);
44 let (body, source_map) = Body::new(db, resolver, file_id, params, body); 44 let (body, source_map) = Body::new(db, expander, params, body);
45 (Arc::new(body), Arc::new(source_map)) 45 (Arc::new(body), Arc::new(source_map))
46} 46}
47 47
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs
index fe5e836f2..afba66069 100644
--- a/crates/ra_hir/src/expr/scope.rs
+++ b/crates/ra_hir/src/expr/scope.rs
@@ -166,6 +166,7 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope
166 166
167#[cfg(test)] 167#[cfg(test)]
168mod tests { 168mod tests {
169 use hir_expand::Source;
169 use ra_db::{fixture::WithFixture, SourceDatabase}; 170 use ra_db::{fixture::WithFixture, SourceDatabase};
170 use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; 171 use ra_syntax::{algo::find_node_at_offset, ast, AstNode};
171 use test_utils::{assert_eq_text, extract_offset}; 172 use test_utils::{assert_eq_text, extract_offset};
@@ -189,7 +190,10 @@ mod tests {
189 let analyzer = SourceAnalyzer::new(&db, file_id, marker.syntax(), None); 190 let analyzer = SourceAnalyzer::new(&db, file_id, marker.syntax(), None);
190 191
191 let scopes = analyzer.scopes(); 192 let scopes = analyzer.scopes();
192 let expr_id = analyzer.body_source_map().node_expr(&marker.into()).unwrap(); 193 let expr_id = analyzer
194 .body_source_map()
195 .node_expr(Source { file_id: file_id.into(), ast: &marker.into() })
196 .unwrap();
193 let scope = scopes.scope_for(expr_id); 197 let scope = scopes.scope_for(expr_id);
194 198
195 let actual = scopes 199 let actual = scopes
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index 2c441b0f4..4b561c63d 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -145,7 +145,8 @@ impl Local {
145 Some(res) 145 Some(res)
146 })?; 146 })?;
147 let (_body, source_map) = db.body_with_source_map(parent); 147 let (_body, source_map) = db.body_with_source_map(parent);
148 let pat_id = source_map.node_pat(&src.ast.into())?; 148 let src = src.map(ast::Pat::from);
149 let pat_id = source_map.node_pat(src.as_ref())?;
149 Some(Local { parent, pat_id }) 150 Some(Local { parent, pat_id })
150 } 151 }
151} 152}
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index f28e9c931..88eed1137 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -7,8 +7,11 @@
7//! purely for "IDE needs". 7//! purely for "IDE needs".
8use std::sync::Arc; 8use std::sync::Arc;
9 9
10use hir_def::path::known; 10use hir_def::{
11use hir_expand::name::AsName; 11 expr::{ExprId, PatId},
12 path::known,
13};
14use hir_expand::{name::AsName, Source};
12use ra_db::FileId; 15use ra_db::FileId;
13use ra_syntax::{ 16use ra_syntax::{
14 ast::{self, AstNode}, 17 ast::{self, AstNode},
@@ -93,6 +96,8 @@ fn def_with_body_from_child_node(
93/// original source files. It should not be used inside the HIR itself. 96/// original source files. It should not be used inside the HIR itself.
94#[derive(Debug)] 97#[derive(Debug)]
95pub struct SourceAnalyzer { 98pub struct SourceAnalyzer {
99 // FIXME: this doesn't handle macros at all
100 file_id: FileId,
96 resolver: Resolver, 101 resolver: Resolver,
97 body_owner: Option<DefWithBody>, 102 body_owner: Option<DefWithBody>,
98 body_source_map: Option<Arc<BodySourceMap>>, 103 body_source_map: Option<Arc<BodySourceMap>>,
@@ -147,7 +152,7 @@ impl SourceAnalyzer {
147 let source_map = def.body_source_map(db); 152 let source_map = def.body_source_map(db);
148 let scopes = db.expr_scopes(def); 153 let scopes = db.expr_scopes(def);
149 let scope = match offset { 154 let scope = match offset {
150 None => scope_for(&scopes, &source_map, &node), 155 None => scope_for(&scopes, &source_map, file_id.into(), &node),
151 Some(offset) => scope_for_offset(&scopes, &source_map, file_id.into(), offset), 156 Some(offset) => scope_for_offset(&scopes, &source_map, file_id.into(), offset),
152 }; 157 };
153 let resolver = expr::resolver_for_scope(db, def, scope); 158 let resolver = expr::resolver_for_scope(db, def, scope);
@@ -157,6 +162,7 @@ impl SourceAnalyzer {
157 body_source_map: Some(source_map), 162 body_source_map: Some(source_map),
158 infer: Some(def.infer(db)), 163 infer: Some(def.infer(db)),
159 scopes: Some(scopes), 164 scopes: Some(scopes),
165 file_id,
160 } 166 }
161 } else { 167 } else {
162 SourceAnalyzer { 168 SourceAnalyzer {
@@ -168,17 +174,28 @@ impl SourceAnalyzer {
168 body_source_map: None, 174 body_source_map: None,
169 infer: None, 175 infer: None,
170 scopes: None, 176 scopes: None,
177 file_id,
171 } 178 }
172 } 179 }
173 } 180 }
174 181
182 fn expr_id(&self, expr: &ast::Expr) -> Option<ExprId> {
183 let src = Source { file_id: self.file_id.into(), ast: expr };
184 self.body_source_map.as_ref()?.node_expr(src)
185 }
186
187 fn pat_id(&self, pat: &ast::Pat) -> Option<PatId> {
188 let src = Source { file_id: self.file_id.into(), ast: pat };
189 self.body_source_map.as_ref()?.node_pat(src)
190 }
191
175 pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option<crate::Ty> { 192 pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option<crate::Ty> {
176 let expr_id = self.body_source_map.as_ref()?.node_expr(expr)?; 193 let expr_id = self.expr_id(expr)?;
177 Some(self.infer.as_ref()?[expr_id].clone()) 194 Some(self.infer.as_ref()?[expr_id].clone())
178 } 195 }
179 196
180 pub fn type_of_pat(&self, _db: &impl HirDatabase, pat: &ast::Pat) -> Option<crate::Ty> { 197 pub fn type_of_pat(&self, _db: &impl HirDatabase, pat: &ast::Pat) -> Option<crate::Ty> {
181 let pat_id = self.body_source_map.as_ref()?.node_pat(pat)?; 198 let pat_id = self.pat_id(pat)?;
182 Some(self.infer.as_ref()?[pat_id].clone()) 199 Some(self.infer.as_ref()?[pat_id].clone())
183 } 200 }
184 201
@@ -191,22 +208,22 @@ impl SourceAnalyzer {
191 } 208 }
192 209
193 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { 210 pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
194 let expr_id = self.body_source_map.as_ref()?.node_expr(&call.clone().into())?; 211 let expr_id = self.expr_id(&call.clone().into())?;
195 self.infer.as_ref()?.method_resolution(expr_id) 212 self.infer.as_ref()?.method_resolution(expr_id)
196 } 213 }
197 214
198 pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<crate::StructField> { 215 pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<crate::StructField> {
199 let expr_id = self.body_source_map.as_ref()?.node_expr(&field.clone().into())?; 216 let expr_id = self.expr_id(&field.clone().into())?;
200 self.infer.as_ref()?.field_resolution(expr_id) 217 self.infer.as_ref()?.field_resolution(expr_id)
201 } 218 }
202 219
203 pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<crate::VariantDef> { 220 pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<crate::VariantDef> {
204 let expr_id = self.body_source_map.as_ref()?.node_expr(&record_lit.clone().into())?; 221 let expr_id = self.expr_id(&record_lit.clone().into())?;
205 self.infer.as_ref()?.variant_resolution_for_expr(expr_id) 222 self.infer.as_ref()?.variant_resolution_for_expr(expr_id)
206 } 223 }
207 224
208 pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option<crate::VariantDef> { 225 pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option<crate::VariantDef> {
209 let pat_id = self.body_source_map.as_ref()?.node_pat(&record_pat.clone().into())?; 226 let pat_id = self.pat_id(&record_pat.clone().into())?;
210 self.infer.as_ref()?.variant_resolution_for_pat(pat_id) 227 self.infer.as_ref()?.variant_resolution_for_pat(pat_id)
211 } 228 }
212 229
@@ -264,13 +281,13 @@ impl SourceAnalyzer {
264 281
265 pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> { 282 pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> {
266 if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) { 283 if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) {
267 let expr_id = self.body_source_map.as_ref()?.node_expr(&path_expr.into())?; 284 let expr_id = self.expr_id(&path_expr.into())?;
268 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { 285 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) {
269 return Some(PathResolution::AssocItem(assoc)); 286 return Some(PathResolution::AssocItem(assoc));
270 } 287 }
271 } 288 }
272 if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { 289 if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) {
273 let pat_id = self.body_source_map.as_ref()?.node_pat(&path_pat.into())?; 290 let pat_id = self.pat_id(&path_pat.into())?;
274 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) { 291 if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) {
275 return Some(PathResolution::AssocItem(assoc)); 292 return Some(PathResolution::AssocItem(assoc));
276 } 293 }
@@ -285,7 +302,7 @@ impl SourceAnalyzer {
285 let name = name_ref.as_name(); 302 let name = name_ref.as_name();
286 let source_map = self.body_source_map.as_ref()?; 303 let source_map = self.body_source_map.as_ref()?;
287 let scopes = self.scopes.as_ref()?; 304 let scopes = self.scopes.as_ref()?;
288 let scope = scope_for(scopes, source_map, name_ref.syntax()); 305 let scope = scope_for(scopes, source_map, self.file_id.into(), name_ref.syntax());
289 let ret = scopes 306 let ret = scopes
290 .scope_chain(scope) 307 .scope_chain(scope)
291 .flat_map(|scope| scopes.entries(scope).iter()) 308 .flat_map(|scope| scopes.entries(scope).iter())
@@ -418,11 +435,12 @@ impl SourceAnalyzer {
418fn scope_for( 435fn scope_for(
419 scopes: &ExprScopes, 436 scopes: &ExprScopes,
420 source_map: &BodySourceMap, 437 source_map: &BodySourceMap,
438 file_id: HirFileId,
421 node: &SyntaxNode, 439 node: &SyntaxNode,
422) -> Option<ScopeId> { 440) -> Option<ScopeId> {
423 node.ancestors() 441 node.ancestors()
424 .filter_map(ast::Expr::cast) 442 .filter_map(ast::Expr::cast)
425 .filter_map(|it| source_map.node_expr(&it)) 443 .filter_map(|it| source_map.node_expr(Source { file_id, ast: &it }))
426 .find_map(|it| scopes.scope_for(it)) 444 .find_map(|it| scopes.scope_for(it))
427} 445}
428 446
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index ac8f8261b..75bba31c2 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -3,9 +3,12 @@ mod lower;
3 3
4use std::{ops::Index, sync::Arc}; 4use std::{ops::Index, sync::Arc};
5 5
6use hir_expand::{either::Either, HirFileId, MacroDefId, Source}; 6use hir_expand::{
7 either::Either, hygiene::Hygiene, AstId, HirFileId, MacroCallLoc, MacroDefId, MacroFileKind,
8 Source,
9};
7use ra_arena::{map::ArenaMap, Arena}; 10use ra_arena::{map::ArenaMap, Arena};
8use ra_syntax::{ast, AstPtr}; 11use ra_syntax::{ast, AstNode, AstPtr};
9use rustc_hash::FxHashMap; 12use rustc_hash::FxHashMap;
10 13
11use crate::{ 14use crate::{
@@ -16,25 +19,87 @@ use crate::{
16 ModuleId, 19 ModuleId,
17}; 20};
18 21
19pub struct MacroResolver { 22pub struct Expander {
20 crate_def_map: Arc<CrateDefMap>, 23 crate_def_map: Arc<CrateDefMap>,
24 current_file_id: HirFileId,
25 hygiene: Hygiene,
21 module: ModuleId, 26 module: ModuleId,
22} 27}
23 28
24impl MacroResolver { 29impl Expander {
25 pub fn new(db: &impl DefDatabase2, module: ModuleId) -> MacroResolver { 30 pub fn new(db: &impl DefDatabase2, current_file_id: HirFileId, module: ModuleId) -> Expander {
26 MacroResolver { crate_def_map: db.crate_def_map(module.krate), module } 31 let crate_def_map = db.crate_def_map(module.krate);
32 let hygiene = Hygiene::new(db, current_file_id);
33 Expander { crate_def_map, current_file_id, hygiene, module }
27 } 34 }
28 35
29 pub(crate) fn resolve_path_as_macro( 36 fn expand(
30 &self, 37 &mut self,
31 db: &impl DefDatabase2, 38 db: &impl DefDatabase2,
32 path: &Path, 39 macro_call: ast::MacroCall,
33 ) -> Option<MacroDefId> { 40 ) -> Option<(Mark, ast::Expr)> {
41 let ast_id = AstId::new(
42 self.current_file_id,
43 db.ast_id_map(self.current_file_id).ast_id(&macro_call),
44 );
45
46 if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) {
47 if let Some(def) = self.resolve_path_as_macro(db, &path) {
48 let call_id = db.intern_macro(MacroCallLoc { def, ast_id });
49 let file_id = call_id.as_file(MacroFileKind::Expr);
50 if let Some(node) = db.parse_or_expand(file_id) {
51 if let Some(expr) = ast::Expr::cast(node) {
52 log::debug!("macro expansion {:#?}", expr.syntax());
53 let mark = self.enter(db, file_id);
54 return Some((mark, expr));
55 }
56 }
57 }
58 }
59
60 // FIXME: Instead of just dropping the error from expansion
61 // report it
62 None
63 }
64
65 fn enter(&mut self, db: &impl DefDatabase2, file_id: HirFileId) -> Mark {
66 let mark = Mark { file_id: self.current_file_id };
67 self.hygiene = Hygiene::new(db, file_id);
68 self.current_file_id = file_id;
69 mark
70 }
71
72 fn exit(&mut self, db: &impl DefDatabase2, mark: Mark) {
73 self.hygiene = Hygiene::new(db, mark.file_id);
74 self.current_file_id = mark.file_id;
75 std::mem::forget(mark);
76 }
77
78 fn to_source<T>(&self, ast: T) -> Source<T> {
79 Source { file_id: self.current_file_id, ast }
80 }
81
82 fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
83 Path::from_src(path, &self.hygiene)
84 }
85
86 fn resolve_path_as_macro(&self, db: &impl DefDatabase2, path: &Path) -> Option<MacroDefId> {
34 self.crate_def_map.resolve_path(db, self.module.module_id, path).0.get_macros() 87 self.crate_def_map.resolve_path(db, self.module.module_id, path).0.get_macros()
35 } 88 }
36} 89}
37 90
91struct Mark {
92 file_id: HirFileId,
93}
94
95impl Drop for Mark {
96 fn drop(&mut self) {
97 if !std::thread::panicking() {
98 panic!("dropped mark")
99 }
100 }
101}
102
38/// The body of an item (function, const etc.). 103/// The body of an item (function, const etc.).
39#[derive(Debug, Eq, PartialEq)] 104#[derive(Debug, Eq, PartialEq)]
40pub struct Body { 105pub struct Body {
@@ -70,9 +135,9 @@ pub type PatSource = Source<PatPtr>;
70/// this properly for macros. 135/// this properly for macros.
71#[derive(Default, Debug, Eq, PartialEq)] 136#[derive(Default, Debug, Eq, PartialEq)]
72pub struct BodySourceMap { 137pub struct BodySourceMap {
73 expr_map: FxHashMap<ExprPtr, ExprId>, 138 expr_map: FxHashMap<ExprSource, ExprId>,
74 expr_map_back: ArenaMap<ExprId, ExprSource>, 139 expr_map_back: ArenaMap<ExprId, ExprSource>,
75 pat_map: FxHashMap<PatPtr, PatId>, 140 pat_map: FxHashMap<PatSource, PatId>,
76 pat_map_back: ArenaMap<PatId, PatSource>, 141 pat_map_back: ArenaMap<PatId, PatSource>,
77 field_map: FxHashMap<(ExprId, usize), AstPtr<ast::RecordField>>, 142 field_map: FxHashMap<(ExprId, usize), AstPtr<ast::RecordField>>,
78} 143}
@@ -80,12 +145,11 @@ pub struct BodySourceMap {
80impl Body { 145impl Body {
81 pub fn new( 146 pub fn new(
82 db: &impl DefDatabase2, 147 db: &impl DefDatabase2,
83 resolver: MacroResolver, 148 expander: Expander,
84 file_id: HirFileId,
85 params: Option<ast::ParamList>, 149 params: Option<ast::ParamList>,
86 body: Option<ast::Expr>, 150 body: Option<ast::Expr>,
87 ) -> (Body, BodySourceMap) { 151 ) -> (Body, BodySourceMap) {
88 lower::lower(db, resolver, file_id, params, body) 152 lower::lower(db, expander, params, body)
89 } 153 }
90 154
91 pub fn params(&self) -> &[PatId] { 155 pub fn params(&self) -> &[PatId] {
@@ -126,16 +190,18 @@ impl BodySourceMap {
126 self.expr_map_back.get(expr).copied() 190 self.expr_map_back.get(expr).copied()
127 } 191 }
128 192
129 pub fn node_expr(&self, node: &ast::Expr) -> Option<ExprId> { 193 pub fn node_expr(&self, node: Source<&ast::Expr>) -> Option<ExprId> {
130 self.expr_map.get(&Either::A(AstPtr::new(node))).cloned() 194 let src = node.map(|it| Either::A(AstPtr::new(it)));
195 self.expr_map.get(&src).cloned()
131 } 196 }
132 197
133 pub fn pat_syntax(&self, pat: PatId) -> Option<PatSource> { 198 pub fn pat_syntax(&self, pat: PatId) -> Option<PatSource> {
134 self.pat_map_back.get(pat).copied() 199 self.pat_map_back.get(pat).copied()
135 } 200 }
136 201
137 pub fn node_pat(&self, node: &ast::Pat) -> Option<PatId> { 202 pub fn node_pat(&self, node: Source<&ast::Pat>) -> Option<PatId> {
138 self.pat_map.get(&Either::A(AstPtr::new(node))).cloned() 203 let src = node.map(|it| Either::A(AstPtr::new(it)));
204 self.pat_map.get(&src).cloned()
139 } 205 }
140 206
141 pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::RecordField> { 207 pub fn field_syntax(&self, expr: ExprId, field: usize) -> AstPtr<ast::RecordField> {
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index 2aa863c9e..f6d79ddf0 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -2,9 +2,7 @@
2 2
3use hir_expand::{ 3use hir_expand::{
4 either::Either, 4 either::Either,
5 hygiene::Hygiene,
6 name::{self, AsName, Name}, 5 name::{self, AsName, Name},
7 AstId, HirFileId, MacroCallLoc, MacroFileKind, Source,
8}; 6};
9use ra_arena::Arena; 7use ra_arena::Arena;
10use ra_syntax::{ 8use ra_syntax::{
@@ -16,7 +14,7 @@ use ra_syntax::{
16}; 14};
17 15
18use crate::{ 16use crate::{
19 body::{Body, BodySourceMap, MacroResolver, PatPtr}, 17 body::{Body, BodySourceMap, Expander, PatPtr},
20 builtin_type::{BuiltinFloat, BuiltinInt}, 18 builtin_type::{BuiltinFloat, BuiltinInt},
21 db::DefDatabase2, 19 db::DefDatabase2,
22 expr::{ 20 expr::{
@@ -30,16 +28,13 @@ use crate::{
30 28
31pub(super) fn lower( 29pub(super) fn lower(
32 db: &impl DefDatabase2, 30 db: &impl DefDatabase2,
33 resolver: MacroResolver, 31 expander: Expander,
34 file_id: HirFileId,
35 params: Option<ast::ParamList>, 32 params: Option<ast::ParamList>,
36 body: Option<ast::Expr>, 33 body: Option<ast::Expr>,
37) -> (Body, BodySourceMap) { 34) -> (Body, BodySourceMap) {
38 ExprCollector { 35 ExprCollector {
39 resolver, 36 expander,
40 db, 37 db,
41 original_file_id: file_id,
42 current_file_id: file_id,
43 source_map: BodySourceMap::default(), 38 source_map: BodySourceMap::default(),
44 body: Body { 39 body: Body {
45 exprs: Arena::default(), 40 exprs: Arena::default(),
@@ -53,9 +48,7 @@ pub(super) fn lower(
53 48
54struct ExprCollector<DB> { 49struct ExprCollector<DB> {
55 db: DB, 50 db: DB,
56 resolver: MacroResolver, 51 expander: Expander,
57 original_file_id: HirFileId,
58 current_file_id: HirFileId,
59 52
60 body: Body, 53 body: Body,
61 source_map: BodySourceMap, 54 source_map: BodySourceMap,
@@ -101,12 +94,9 @@ where
101 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { 94 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
102 let ptr = Either::A(ptr); 95 let ptr = Either::A(ptr);
103 let id = self.body.exprs.alloc(expr); 96 let id = self.body.exprs.alloc(expr);
104 if self.current_file_id == self.original_file_id { 97 let src = self.expander.to_source(ptr);
105 self.source_map.expr_map.insert(ptr, id); 98 self.source_map.expr_map.insert(src, id);
106 } 99 self.source_map.expr_map_back.insert(id, src);
107 self.source_map
108 .expr_map_back
109 .insert(id, Source { file_id: self.current_file_id, ast: ptr });
110 id 100 id
111 } 101 }
112 // desugared exprs don't have ptr, that's wrong and should be fixed 102 // desugared exprs don't have ptr, that's wrong and should be fixed
@@ -117,20 +107,16 @@ where
117 fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr<ast::RecordField>) -> ExprId { 107 fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr<ast::RecordField>) -> ExprId {
118 let ptr = Either::B(ptr); 108 let ptr = Either::B(ptr);
119 let id = self.body.exprs.alloc(expr); 109 let id = self.body.exprs.alloc(expr);
120 if self.current_file_id == self.original_file_id { 110 let src = self.expander.to_source(ptr);
121 self.source_map.expr_map.insert(ptr, id); 111 self.source_map.expr_map.insert(src, id);
122 } 112 self.source_map.expr_map_back.insert(id, src);
123 self.source_map
124 .expr_map_back
125 .insert(id, Source { file_id: self.current_file_id, ast: ptr });
126 id 113 id
127 } 114 }
128 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { 115 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
129 let id = self.body.pats.alloc(pat); 116 let id = self.body.pats.alloc(pat);
130 if self.current_file_id == self.original_file_id { 117 let src = self.expander.to_source(ptr);
131 self.source_map.pat_map.insert(ptr, id); 118 self.source_map.pat_map.insert(src, id);
132 } 119 self.source_map.pat_map_back.insert(id, src);
133 self.source_map.pat_map_back.insert(id, Source { file_id: self.current_file_id, ast: ptr });
134 id 120 id
135 } 121 }
136 122
@@ -272,7 +258,7 @@ where
272 ast::Expr::PathExpr(e) => { 258 ast::Expr::PathExpr(e) => {
273 let path = e 259 let path = e
274 .path() 260 .path()
275 .and_then(|path| self.parse_path(path)) 261 .and_then(|path| self.expander.parse_path(path))
276 .map(Expr::Path) 262 .map(Expr::Path)
277 .unwrap_or(Expr::Missing); 263 .unwrap_or(Expr::Missing);
278 self.alloc_expr(path, syntax_ptr) 264 self.alloc_expr(path, syntax_ptr)
@@ -288,7 +274,8 @@ where
288 ast::Expr::ParenExpr(e) => { 274 ast::Expr::ParenExpr(e) => {
289 let inner = self.collect_expr_opt(e.expr()); 275 let inner = self.collect_expr_opt(e.expr());
290 // make the paren expr point to the inner expression as well 276 // make the paren expr point to the inner expression as well
291 self.source_map.expr_map.insert(Either::A(syntax_ptr), inner); 277 let src = self.expander.to_source(Either::A(syntax_ptr));
278 self.source_map.expr_map.insert(src, inner);
292 inner 279 inner
293 } 280 }
294 ast::Expr::ReturnExpr(e) => { 281 ast::Expr::ReturnExpr(e) => {
@@ -296,7 +283,7 @@ where
296 self.alloc_expr(Expr::Return { expr }, syntax_ptr) 283 self.alloc_expr(Expr::Return { expr }, syntax_ptr)
297 } 284 }
298 ast::Expr::RecordLit(e) => { 285 ast::Expr::RecordLit(e) => {
299 let path = e.path().and_then(|path| self.parse_path(path)); 286 let path = e.path().and_then(|path| self.expander.parse_path(path));
300 let mut field_ptrs = Vec::new(); 287 let mut field_ptrs = Vec::new();
301 let record_lit = if let Some(nfl) = e.record_field_list() { 288 let record_lit = if let Some(nfl) = e.record_field_list() {
302 let fields = nfl 289 let fields = nfl
@@ -443,32 +430,14 @@ where
443 // FIXME implement HIR for these: 430 // FIXME implement HIR for these:
444 ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 431 ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
445 ast::Expr::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 432 ast::Expr::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
446 ast::Expr::MacroCall(e) => { 433 ast::Expr::MacroCall(e) => match self.expander.expand(self.db, e) {
447 let ast_id = AstId::new( 434 Some((mark, expansion)) => {
448 self.current_file_id, 435 let id = self.collect_expr(expansion);
449 self.db.ast_id_map(self.current_file_id).ast_id(&e), 436 self.expander.exit(self.db, mark);
450 ); 437 id
451
452 if let Some(path) = e.path().and_then(|path| self.parse_path(path)) {
453 if let Some(def) = self.resolver.resolve_path_as_macro(self.db, &path) {
454 let call_id = self.db.intern_macro(MacroCallLoc { def, ast_id });
455 let file_id = call_id.as_file(MacroFileKind::Expr);
456 if let Some(node) = self.db.parse_or_expand(file_id) {
457 if let Some(expr) = ast::Expr::cast(node) {
458 log::debug!("macro expansion {:#?}", expr.syntax());
459 let old_file_id =
460 std::mem::replace(&mut self.current_file_id, file_id);
461 let id = self.collect_expr(expr);
462 self.current_file_id = old_file_id;
463 return id;
464 }
465 }
466 }
467 } 438 }
468 // FIXME: Instead of just dropping the error from expansion 439 None => self.alloc_expr(Expr::Missing, syntax_ptr),
469 // report it 440 },
470 self.alloc_expr(Expr::Missing, syntax_ptr)
471 }
472 } 441 }
473 } 442 }
474 443
@@ -519,7 +488,7 @@ where
519 Pat::Bind { name, mode: annotation, subpat } 488 Pat::Bind { name, mode: annotation, subpat }
520 } 489 }
521 ast::Pat::TupleStructPat(p) => { 490 ast::Pat::TupleStructPat(p) => {
522 let path = p.path().and_then(|path| self.parse_path(path)); 491 let path = p.path().and_then(|path| self.expander.parse_path(path));
523 let args = p.args().map(|p| self.collect_pat(p)).collect(); 492 let args = p.args().map(|p| self.collect_pat(p)).collect();
524 Pat::TupleStruct { path, args } 493 Pat::TupleStruct { path, args }
525 } 494 }
@@ -529,7 +498,7 @@ where
529 Pat::Ref { pat, mutability } 498 Pat::Ref { pat, mutability }
530 } 499 }
531 ast::Pat::PathPat(p) => { 500 ast::Pat::PathPat(p) => {
532 let path = p.path().and_then(|path| self.parse_path(path)); 501 let path = p.path().and_then(|path| self.expander.parse_path(path));
533 path.map(Pat::Path).unwrap_or(Pat::Missing) 502 path.map(Pat::Path).unwrap_or(Pat::Missing)
534 } 503 }
535 ast::Pat::TuplePat(p) => { 504 ast::Pat::TuplePat(p) => {
@@ -538,7 +507,7 @@ where
538 } 507 }
539 ast::Pat::PlaceholderPat(_) => Pat::Wild, 508 ast::Pat::PlaceholderPat(_) => Pat::Wild,
540 ast::Pat::RecordPat(p) => { 509 ast::Pat::RecordPat(p) => {
541 let path = p.path().and_then(|path| self.parse_path(path)); 510 let path = p.path().and_then(|path| self.expander.parse_path(path));
542 let record_field_pat_list = 511 let record_field_pat_list =
543 p.record_field_pat_list().expect("every struct should have a field list"); 512 p.record_field_pat_list().expect("every struct should have a field list");
544 let mut fields: Vec<_> = record_field_pat_list 513 let mut fields: Vec<_> = record_field_pat_list
@@ -579,11 +548,6 @@ where
579 self.missing_pat() 548 self.missing_pat()
580 } 549 }
581 } 550 }
582
583 fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
584 let hygiene = Hygiene::new(self.db, self.current_file_id);
585 Path::from_src(path, &hygiene)
586 }
587} 551}
588 552
589impl From<ast::BinOp> for BinaryOp { 553impl From<ast::BinOp> for BinaryOp {
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs
index c6ffa2c6f..930789b0f 100644
--- a/crates/ra_hir_expand/src/lib.rs
+++ b/crates/ra_hir_expand/src/lib.rs
@@ -223,7 +223,7 @@ impl<N: AstNode> AstId<N> {
223 } 223 }
224} 224}
225 225
226#[derive(Debug, PartialEq, Eq, Clone, Copy)] 226#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
227pub struct Source<T> { 227pub struct Source<T> {
228 pub file_id: HirFileId, 228 pub file_id: HirFileId,
229 pub ast: T, 229 pub ast: T,
@@ -233,6 +233,9 @@ impl<T> Source<T> {
233 pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> Source<U> { 233 pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> Source<U> {
234 Source { file_id: self.file_id, ast: f(self.ast) } 234 Source { file_id: self.file_id, ast: f(self.ast) }
235 } 235 }
236 pub fn as_ref(&self) -> Source<&T> {
237 Source { file_id: self.file_id, ast: &self.ast }
238 }
236 pub fn file_syntax(&self, db: &impl db::AstDatabase) -> SyntaxNode { 239 pub fn file_syntax(&self, db: &impl db::AstDatabase) -> SyntaxNode {
237 db.parse_or_expand(self.file_id).expect("source created from invalid file") 240 db.parse_or_expand(self.file_id).expect("source created from invalid file")
238 } 241 }