aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/expr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/expr.rs')
-rw-r--r--crates/ra_hir/src/expr.rs53
1 files changed, 38 insertions, 15 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index db74d28e8..cdadf3ba6 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -10,7 +10,7 @@ use ra_syntax::{
10}; 10};
11 11
12use crate::{ 12use crate::{
13 Path, Name, HirDatabase, Resolver,DefWithBody, Either, 13 Path, Name, HirDatabase, Resolver,DefWithBody, Either, HirFileId,
14 name::AsName, 14 name::AsName,
15 ids::{MacroCallId}, 15 ids::{MacroCallId},
16 type_ref::{Mutability, TypeRef}, 16 type_ref::{Mutability, TypeRef},
@@ -488,15 +488,19 @@ pub(crate) struct ExprCollector<DB> {
488 params: Vec<PatId>, 488 params: Vec<PatId>,
489 body_expr: Option<ExprId>, 489 body_expr: Option<ExprId>,
490 resolver: Resolver, 490 resolver: Resolver,
491 // FIXEME: Its a quick hack,see issue #1196 491 // Expr collector expands macros along the way. original points to the file
492 is_in_macro: bool, 492 // we started with, current points to the current macro expansion. source
493 // maps don't support macros yet, so we only record info into source map if
494 // current == original (see #1196)
495 original_file_id: HirFileId,
496 current_file_id: HirFileId,
493} 497}
494 498
495impl<'a, DB> ExprCollector<&'a DB> 499impl<'a, DB> ExprCollector<&'a DB>
496where 500where
497 DB: HirDatabase, 501 DB: HirDatabase,
498{ 502{
499 fn new(owner: DefWithBody, resolver: Resolver, db: &'a DB) -> Self { 503 fn new(owner: DefWithBody, file_id: HirFileId, resolver: Resolver, db: &'a DB) -> Self {
500 ExprCollector { 504 ExprCollector {
501 owner, 505 owner,
502 resolver, 506 resolver,
@@ -506,23 +510,23 @@ where
506 source_map: BodySourceMap::default(), 510 source_map: BodySourceMap::default(),
507 params: Vec::new(), 511 params: Vec::new(),
508 body_expr: None, 512 body_expr: None,
509 is_in_macro: false, 513 original_file_id: file_id,
514 current_file_id: file_id,
510 } 515 }
511 } 516 }
512 fn alloc_expr(&mut self, expr: Expr, syntax_ptr: SyntaxNodePtr) -> ExprId { 517 fn alloc_expr(&mut self, expr: Expr, syntax_ptr: SyntaxNodePtr) -> ExprId {
513 let id = self.exprs.alloc(expr); 518 let id = self.exprs.alloc(expr);
514 if !self.is_in_macro { 519 if self.current_file_id == self.original_file_id {
515 self.source_map.expr_map.insert(syntax_ptr, id); 520 self.source_map.expr_map.insert(syntax_ptr, id);
516 self.source_map.expr_map_back.insert(id, syntax_ptr); 521 self.source_map.expr_map_back.insert(id, syntax_ptr);
517 } 522 }
518
519 id 523 id
520 } 524 }
521 525
522 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { 526 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
523 let id = self.pats.alloc(pat); 527 let id = self.pats.alloc(pat);
524 528
525 if !self.is_in_macro { 529 if self.current_file_id == self.original_file_id {
526 self.source_map.pat_map.insert(ptr, id); 530 self.source_map.pat_map.insert(ptr, id);
527 self.source_map.pat_map_back.insert(id, ptr); 531 self.source_map.pat_map_back.insert(id, ptr);
528 } 532 }
@@ -815,12 +819,19 @@ where
815 // very hacky.FIXME change to use the macro resolution 819 // very hacky.FIXME change to use the macro resolution
816 let path = e.path().and_then(Path::from_ast); 820 let path = e.path().and_then(Path::from_ast);
817 821
818 if let Some(call_id) = self.resolver.resolve_macro_call(self.db, path, e) { 822 let ast_id = self
823 .db
824 .ast_id_map(self.current_file_id)
825 .ast_id(e)
826 .with_file_id(self.current_file_id);
827
828 if let Some(call_id) = self.resolver.resolve_macro_call(self.db, path, ast_id) {
819 if let Some(expr) = expand_macro_to_expr(self.db, call_id, e.token_tree()) { 829 if let Some(expr) = expand_macro_to_expr(self.db, call_id, e.token_tree()) {
820 log::debug!("macro expansion {}", expr.syntax().debug_dump()); 830 log::debug!("macro expansion {}", expr.syntax().debug_dump());
821 let old = std::mem::replace(&mut self.is_in_macro, true); 831 let old_file_id =
832 std::mem::replace(&mut self.current_file_id, call_id.into());
822 let id = self.collect_expr(&expr); 833 let id = self.collect_expr(&expr);
823 self.is_in_macro = old; 834 self.current_file_id = old_file_id;
824 id 835 id
825 } else { 836 } else {
826 // FIXME: Instead of just dropping the error from expansion 837 // FIXME: Instead of just dropping the error from expansion
@@ -1006,12 +1017,24 @@ pub(crate) fn body_with_source_map_query(
1006 db: &impl HirDatabase, 1017 db: &impl HirDatabase,
1007 def: DefWithBody, 1018 def: DefWithBody,
1008) -> (Arc<Body>, Arc<BodySourceMap>) { 1019) -> (Arc<Body>, Arc<BodySourceMap>) {
1009 let mut collector = ExprCollector::new(def, def.resolver(db), db); 1020 let mut collector;
1010 1021
1011 match def { 1022 match def {
1012 DefWithBody::Const(ref c) => collector.collect_const_body(&c.source(db).1), 1023 DefWithBody::Const(ref c) => {
1013 DefWithBody::Function(ref f) => collector.collect_fn_body(&f.source(db).1), 1024 let (file_id, src) = c.source(db);
1014 DefWithBody::Static(ref s) => collector.collect_static_body(&s.source(db).1), 1025 collector = ExprCollector::new(def, file_id, def.resolver(db), db);
1026 collector.collect_const_body(&src)
1027 }
1028 DefWithBody::Function(ref f) => {
1029 let (file_id, src) = f.source(db);
1030 collector = ExprCollector::new(def, file_id, def.resolver(db), db);
1031 collector.collect_fn_body(&src)
1032 }
1033 DefWithBody::Static(ref s) => {
1034 let (file_id, src) = s.source(db);
1035 collector = ExprCollector::new(def, file_id, def.resolver(db), db);
1036 collector.collect_static_body(&src)
1037 }
1015 } 1038 }
1016 1039
1017 let (body, source_map) = collector.finish(); 1040 let (body, source_map) = collector.finish();