diff options
Diffstat (limited to 'crates/ra_hir/src/expr.rs')
-rw-r--r-- | crates/ra_hir/src/expr.rs | 53 |
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 | ||
12 | use crate::{ | 12 | use 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 | ||
495 | impl<'a, DB> ExprCollector<&'a DB> | 499 | impl<'a, DB> ExprCollector<&'a DB> |
496 | where | 500 | where |
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(); |