diff options
author | Lenard Pratt <[email protected]> | 2019-04-18 19:35:47 +0100 |
---|---|---|
committer | Lenard Pratt <[email protected]> | 2019-04-23 10:17:31 +0100 |
commit | 1ab7066e32ab482c70ea5c9bba7585eba275476a (patch) | |
tree | a754785d91783b713e54b70058f2f16984d25074 /crates/ra_hir/src/expr.rs | |
parent | ce211434a6501e88cb83462f2443db085f1557d3 (diff) |
Introduced resolve_macro_call on resolver
changed to manual expansion
fix for nested macros
Diffstat (limited to 'crates/ra_hir/src/expr.rs')
-rw-r--r-- | crates/ra_hir/src/expr.rs | 104 |
1 files changed, 55 insertions, 49 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 7d5257461..db74d28e8 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -5,14 +5,14 @@ use rustc_hash::FxHashMap; | |||
5 | 5 | ||
6 | use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; | 6 | use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; |
7 | use ra_syntax::{ | 7 | use ra_syntax::{ |
8 | SyntaxNodePtr, AstPtr, AstNode, | 8 | SyntaxNodePtr, AstPtr, AstNode,TreeArc, |
9 | ast::{self, LoopBodyOwner, ArgListOwner, NameOwner, LiteralKind,ArrayExprKind, TypeAscriptionOwner} | 9 | ast::{self, LoopBodyOwner, ArgListOwner, NameOwner, LiteralKind,ArrayExprKind, TypeAscriptionOwner} |
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | Path, Name, HirDatabase, Resolver,DefWithBody, Either, | 13 | Path, Name, HirDatabase, Resolver,DefWithBody, Either, |
14 | name::AsName, | 14 | name::AsName, |
15 | ids::{MacroCallLoc,HirFileId}, | 15 | ids::{MacroCallId}, |
16 | type_ref::{Mutability, TypeRef}, | 16 | type_ref::{Mutability, TypeRef}, |
17 | }; | 17 | }; |
18 | use crate::{path::GenericArgs, ty::primitive::{IntTy, UncertainIntTy, FloatTy, UncertainFloatTy}}; | 18 | use crate::{path::GenericArgs, ty::primitive::{IntTy, UncertainIntTy, FloatTy, UncertainFloatTy}}; |
@@ -488,23 +488,45 @@ 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 | ||
492 | is_in_macro: bool, | ||
491 | } | 493 | } |
492 | 494 | ||
493 | impl<'a, DB> ExprCollector<&'a DB> | 495 | impl<'a, DB> ExprCollector<&'a DB> |
494 | where | 496 | where |
495 | DB: HirDatabase, | 497 | DB: HirDatabase, |
496 | { | 498 | { |
499 | fn new(owner: DefWithBody, resolver: Resolver, db: &'a DB) -> Self { | ||
500 | ExprCollector { | ||
501 | owner, | ||
502 | resolver, | ||
503 | db, | ||
504 | exprs: Arena::default(), | ||
505 | pats: Arena::default(), | ||
506 | source_map: BodySourceMap::default(), | ||
507 | params: Vec::new(), | ||
508 | body_expr: None, | ||
509 | is_in_macro: false, | ||
510 | } | ||
511 | } | ||
497 | fn alloc_expr(&mut self, expr: Expr, syntax_ptr: SyntaxNodePtr) -> ExprId { | 512 | fn alloc_expr(&mut self, expr: Expr, syntax_ptr: SyntaxNodePtr) -> ExprId { |
498 | let id = self.exprs.alloc(expr); | 513 | let id = self.exprs.alloc(expr); |
499 | self.source_map.expr_map.insert(syntax_ptr, id); | 514 | if !self.is_in_macro { |
500 | self.source_map.expr_map_back.insert(id, syntax_ptr); | 515 | self.source_map.expr_map.insert(syntax_ptr, id); |
516 | self.source_map.expr_map_back.insert(id, syntax_ptr); | ||
517 | } | ||
518 | |||
501 | id | 519 | id |
502 | } | 520 | } |
503 | 521 | ||
504 | fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { | 522 | fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { |
505 | let id = self.pats.alloc(pat); | 523 | let id = self.pats.alloc(pat); |
506 | self.source_map.pat_map.insert(ptr, id); | 524 | |
507 | self.source_map.pat_map_back.insert(id, ptr); | 525 | if !self.is_in_macro { |
526 | self.source_map.pat_map.insert(ptr, id); | ||
527 | self.source_map.pat_map_back.insert(id, ptr); | ||
528 | } | ||
529 | |||
508 | id | 530 | id |
509 | } | 531 | } |
510 | 532 | ||
@@ -790,40 +812,19 @@ where | |||
790 | ast::ExprKind::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | 812 | ast::ExprKind::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), |
791 | ast::ExprKind::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | 813 | ast::ExprKind::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), |
792 | ast::ExprKind::MacroCall(e) => { | 814 | ast::ExprKind::MacroCall(e) => { |
793 | // very hacky.TODO change to use the macro resolution | 815 | // very hacky.FIXME change to use the macro resolution |
794 | let name = e | 816 | let path = e.path().and_then(Path::from_ast); |
795 | .path() | 817 | |
796 | .and_then(Path::from_ast) | 818 | if let Some(call_id) = self.resolver.resolve_macro_call(self.db, path, e) { |
797 | .and_then(|path| path.expand_macro_expr()) | 819 | if let Some(expr) = expand_macro_to_expr(self.db, call_id, e.token_tree()) { |
798 | .unwrap_or_else(Name::missing); | 820 | log::debug!("macro expansion {}", expr.syntax().debug_dump()); |
799 | 821 | let old = std::mem::replace(&mut self.is_in_macro, true); | |
800 | if let Some(macro_id) = self.resolver.resolve_macro_call(&name) { | 822 | let id = self.collect_expr(&expr); |
801 | if let Some((module, _)) = self.resolver.module() { | 823 | self.is_in_macro = old; |
802 | // we do this to get the ast_id for the macro call | 824 | id |
803 | // if we used the ast_id from the macro_id variable | ||
804 | // it gives us the ast_id of the defenition site | ||
805 | let module = module.mk_module(module.root()); | ||
806 | let hir_file_id = module.definition_source(self.db).0; | ||
807 | let ast_id = | ||
808 | self.db.ast_id_map(hir_file_id).ast_id(e).with_file_id(hir_file_id); | ||
809 | |||
810 | let call_loc = MacroCallLoc { def: *macro_id, ast_id }; | ||
811 | let call_id = call_loc.id(self.db); | ||
812 | let file_id: HirFileId = call_id.into(); | ||
813 | |||
814 | log::debug!( | ||
815 | "expanded macro ast {}", | ||
816 | self.db.hir_parse(file_id).syntax().debug_dump() | ||
817 | ); | ||
818 | |||
819 | self.db | ||
820 | .hir_parse(file_id) | ||
821 | .syntax() | ||
822 | .descendants() | ||
823 | .find_map(ast::Expr::cast) | ||
824 | .map(|expr| self.collect_expr(expr)) | ||
825 | .unwrap_or(self.alloc_expr(Expr::Missing, syntax_ptr)) | ||
826 | } else { | 825 | } else { |
826 | // FIXME: Instead of just dropping the error from expansion | ||
827 | // report it | ||
827 | self.alloc_expr(Expr::Missing, syntax_ptr) | 828 | self.alloc_expr(Expr::Missing, syntax_ptr) |
828 | } | 829 | } |
829 | } else { | 830 | } else { |
@@ -987,20 +988,25 @@ where | |||
987 | } | 988 | } |
988 | } | 989 | } |
989 | 990 | ||
991 | fn expand_macro_to_expr( | ||
992 | db: &impl HirDatabase, | ||
993 | macro_call: MacroCallId, | ||
994 | args: Option<&ast::TokenTree>, | ||
995 | ) -> Option<TreeArc<ast::Expr>> { | ||
996 | let rules = db.macro_def(macro_call.loc(db).def)?; | ||
997 | |||
998 | let args = mbe::ast_to_token_tree(args?)?.0; | ||
999 | |||
1000 | let expanded = rules.expand(&args).ok()?; | ||
1001 | |||
1002 | mbe::token_tree_to_expr(&expanded).ok() | ||
1003 | } | ||
1004 | |||
990 | pub(crate) fn body_with_source_map_query( | 1005 | pub(crate) fn body_with_source_map_query( |
991 | db: &impl HirDatabase, | 1006 | db: &impl HirDatabase, |
992 | def: DefWithBody, | 1007 | def: DefWithBody, |
993 | ) -> (Arc<Body>, Arc<BodySourceMap>) { | 1008 | ) -> (Arc<Body>, Arc<BodySourceMap>) { |
994 | let mut collector = ExprCollector { | 1009 | let mut collector = ExprCollector::new(def, def.resolver(db), db); |
995 | db, | ||
996 | owner: def, | ||
997 | resolver: def.resolver(db), | ||
998 | exprs: Arena::default(), | ||
999 | pats: Arena::default(), | ||
1000 | source_map: BodySourceMap::default(), | ||
1001 | params: Vec::new(), | ||
1002 | body_expr: None, | ||
1003 | }; | ||
1004 | 1010 | ||
1005 | match def { | 1011 | match def { |
1006 | DefWithBody::Const(ref c) => collector.collect_const_body(&c.source(db).1), | 1012 | DefWithBody::Const(ref c) => collector.collect_const_body(&c.source(db).1), |