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.rs72
1 files changed, 61 insertions, 11 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 817e660f9..db74d28e8 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -5,13 +5,14 @@ use rustc_hash::FxHashMap;
5 5
6use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; 6use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
7use ra_syntax::{ 7use 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
12use crate::{ 12use crate::{
13 Path, Name, HirDatabase, Resolver,DefWithBody, Either, 13 Path, Name, HirDatabase, Resolver,DefWithBody, Either,
14 name::AsName, 14 name::AsName,
15 ids::{MacroCallId},
15 type_ref::{Mutability, TypeRef}, 16 type_ref::{Mutability, TypeRef},
16}; 17};
17use crate::{path::GenericArgs, ty::primitive::{IntTy, UncertainIntTy, FloatTy, UncertainFloatTy}}; 18use crate::{path::GenericArgs, ty::primitive::{IntTy, UncertainIntTy, FloatTy, UncertainFloatTy}};
@@ -478,38 +479,54 @@ impl Pat {
478 479
479// Queries 480// Queries
480 481
481pub(crate) struct ExprCollector { 482pub(crate) struct ExprCollector<DB> {
483 db: DB,
482 owner: DefWithBody, 484 owner: DefWithBody,
483 exprs: Arena<ExprId, Expr>, 485 exprs: Arena<ExprId, Expr>,
484 pats: Arena<PatId, Pat>, 486 pats: Arena<PatId, Pat>,
485 source_map: BodySourceMap, 487 source_map: BodySourceMap,
486 params: Vec<PatId>, 488 params: Vec<PatId>,
487 body_expr: Option<ExprId>, 489 body_expr: Option<ExprId>,
490 resolver: Resolver,
491 // FIXEME: Its a quick hack,see issue #1196
492 is_in_macro: bool,
488} 493}
489 494
490impl ExprCollector { 495impl<'a, DB> ExprCollector<&'a DB>
491 fn new(owner: DefWithBody) -> Self { 496where
497 DB: HirDatabase,
498{
499 fn new(owner: DefWithBody, resolver: Resolver, db: &'a DB) -> Self {
492 ExprCollector { 500 ExprCollector {
493 owner, 501 owner,
502 resolver,
503 db,
494 exprs: Arena::default(), 504 exprs: Arena::default(),
495 pats: Arena::default(), 505 pats: Arena::default(),
496 source_map: BodySourceMap::default(), 506 source_map: BodySourceMap::default(),
497 params: Vec::new(), 507 params: Vec::new(),
498 body_expr: None, 508 body_expr: None,
509 is_in_macro: false,
499 } 510 }
500 } 511 }
501
502 fn alloc_expr(&mut self, expr: Expr, syntax_ptr: SyntaxNodePtr) -> ExprId { 512 fn alloc_expr(&mut self, expr: Expr, syntax_ptr: SyntaxNodePtr) -> ExprId {
503 let id = self.exprs.alloc(expr); 513 let id = self.exprs.alloc(expr);
504 self.source_map.expr_map.insert(syntax_ptr, id); 514 if !self.is_in_macro {
505 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
506 id 519 id
507 } 520 }
508 521
509 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId { 522 fn alloc_pat(&mut self, pat: Pat, ptr: PatPtr) -> PatId {
510 let id = self.pats.alloc(pat); 523 let id = self.pats.alloc(pat);
511 self.source_map.pat_map.insert(ptr, id); 524
512 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
513 id 530 id
514 } 531 }
515 532
@@ -794,7 +811,26 @@ impl ExprCollector {
794 ast::ExprKind::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 811 ast::ExprKind::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
795 ast::ExprKind::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 812 ast::ExprKind::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
796 ast::ExprKind::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 813 ast::ExprKind::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr),
797 ast::ExprKind::MacroCall(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 814 ast::ExprKind::MacroCall(e) => {
815 // very hacky.FIXME change to use the macro resolution
816 let path = e.path().and_then(Path::from_ast);
817
818 if let Some(call_id) = self.resolver.resolve_macro_call(self.db, path, e) {
819 if let Some(expr) = expand_macro_to_expr(self.db, call_id, e.token_tree()) {
820 log::debug!("macro expansion {}", expr.syntax().debug_dump());
821 let old = std::mem::replace(&mut self.is_in_macro, true);
822 let id = self.collect_expr(&expr);
823 self.is_in_macro = old;
824 id
825 } else {
826 // FIXME: Instead of just dropping the error from expansion
827 // report it
828 self.alloc_expr(Expr::Missing, syntax_ptr)
829 }
830 } else {
831 self.alloc_expr(Expr::Missing, syntax_ptr)
832 }
833 }
798 } 834 }
799 } 835 }
800 836
@@ -952,11 +988,25 @@ impl ExprCollector {
952 } 988 }
953} 989}
954 990
991fn 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
955pub(crate) fn body_with_source_map_query( 1005pub(crate) fn body_with_source_map_query(
956 db: &impl HirDatabase, 1006 db: &impl HirDatabase,
957 def: DefWithBody, 1007 def: DefWithBody,
958) -> (Arc<Body>, Arc<BodySourceMap>) { 1008) -> (Arc<Body>, Arc<BodySourceMap>) {
959 let mut collector = ExprCollector::new(def); 1009 let mut collector = ExprCollector::new(def, def.resolver(db), db);
960 1010
961 match def { 1011 match def {
962 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),