aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-05-01 13:53:13 +0100
committerAleksey Kladov <[email protected]>2019-05-01 13:53:13 +0100
commit594aac059e1f8c15a7c856e2778b0c4ff2a240aa (patch)
tree502484ae326c438febf324beb86078f00fe383b4
parent43524a39cd6ac26dc6489f6481220179149c5f08 (diff)
Use correct FileId when expanding macros in expressions
-rw-r--r--crates/ra_hir/src/expr.rs53
-rw-r--r--crates/ra_hir/src/resolve.rs24
2 files changed, 44 insertions, 33 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();
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index d1f97c104..bc9170cdc 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -10,6 +10,7 @@ use crate::{
10 code_model_api::Crate, 10 code_model_api::Crate,
11 MacroCallId, 11 MacroCallId,
12 MacroCallLoc, 12 MacroCallLoc,
13 AstId,
13 db::HirDatabase, 14 db::HirDatabase,
14 name::{Name, KnownName}, 15 name::{Name, KnownName},
15 nameres::{PerNs, CrateDefMap, CrateModuleId}, 16 nameres::{PerNs, CrateDefMap, CrateModuleId},
@@ -17,7 +18,7 @@ use crate::{
17 expr::{scope::{ExprScopes, ScopeId}, PatId}, 18 expr::{scope::{ExprScopes, ScopeId}, PatId},
18 impl_block::ImplBlock, 19 impl_block::ImplBlock,
19 path::Path, 20 path::Path,
20 Trait 21 Trait,
21}; 22};
22 23
23#[derive(Debug, Clone, Default)] 24#[derive(Debug, Clone, Default)]
@@ -138,25 +139,12 @@ impl Resolver {
138 &self, 139 &self,
139 db: &impl HirDatabase, 140 db: &impl HirDatabase,
140 path: Option<Path>, 141 path: Option<Path>,
141 call: &ast::MacroCall, 142 ast_id: AstId<ast::MacroCall>,
142 ) -> Option<MacroCallId> { 143 ) -> Option<MacroCallId> {
143 let name = path.and_then(|path| path.expand_macro_expr()).unwrap_or_else(Name::missing); 144 let name = path.and_then(|path| path.expand_macro_expr()).unwrap_or_else(Name::missing);
144 let macro_def_id = self.module().and_then(|(module, _)| module.find_macro(&name)); 145 let def_id = self.module().and_then(|(module, _)| module.find_macro(&name))?;
145 if let Some(def_id) = macro_def_id { 146 let call_loc = MacroCallLoc { def: *def_id, ast_id }.id(db);
146 self.module().and_then(|(module, _)| { 147 Some(call_loc)
147 // we do this to get the ast_id for the macro call
148 // if we used the ast_id from the def_id variable
149 // it gives us the ast_id of the defenition site
150 let module = module.mk_module(module.root());
151 let hir_file_id = module.definition_source(db).0;
152 let ast_id = db.ast_id_map(hir_file_id).ast_id(call).with_file_id(hir_file_id);
153 let call_loc = MacroCallLoc { def: *def_id, ast_id }.id(db);
154
155 Some(call_loc)
156 })
157 } else {
158 None
159 }
160 } 148 }
161 149
162 /// Returns the resolved path segments 150 /// Returns the resolved path segments