diff options
author | Aleksey Kladov <[email protected]> | 2019-05-01 13:53:13 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-05-01 13:53:13 +0100 |
commit | 594aac059e1f8c15a7c856e2778b0c4ff2a240aa (patch) | |
tree | 502484ae326c438febf324beb86078f00fe383b4 | |
parent | 43524a39cd6ac26dc6489f6481220179149c5f08 (diff) |
Use correct FileId when expanding macros in expressions
-rw-r--r-- | crates/ra_hir/src/expr.rs | 53 | ||||
-rw-r--r-- | crates/ra_hir/src/resolve.rs | 24 |
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 | ||
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(); |
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 |