aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ids.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-03-26 10:09:39 +0000
committerAleksey Kladov <[email protected]>2019-03-26 10:20:54 +0000
commit5270bca5f72fa65f0515be776e06d3d6a4d1efca (patch)
treefa1b8b8ac66713ba29b676e1c2fdd4c4357f24ff /crates/ra_hir/src/ids.rs
parentdc94f3612583c5e960b334761ad0c18d328840ea (diff)
store macro def inside macro id
This solves the problem of "macro expansion can't call into name resolution, because name resolution calls back into macro expansion" Because we store macro def as a part of call id, macro expansion just knows the def!
Diffstat (limited to 'crates/ra_hir/src/ids.rs')
-rw-r--r--crates/ra_hir/src/ids.rs24
1 files changed, 19 insertions, 5 deletions
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 18401f865..cf0566308 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -7,6 +7,7 @@ use std::{
7use ra_db::{LocationInterner, FileId}; 7use ra_db::{LocationInterner, FileId};
8use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, SyntaxNodePtr, ast}; 8use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, SyntaxNodePtr, ast};
9use ra_arena::{Arena, RawId, ArenaId, impl_arena_id}; 9use ra_arena::{Arena, RawId, ArenaId, impl_arena_id};
10use mbe::MacroRules;
10 11
11use crate::{ 12use crate::{
12 Module, 13 Module,
@@ -100,10 +101,7 @@ fn parse_macro(db: &impl DefDatabase, macro_call_id: MacroCallId) -> Option<Tree
100 let macro_call = ast::MacroCall::cast(&syntax).unwrap(); 101 let macro_call = ast::MacroCall::cast(&syntax).unwrap();
101 let (macro_arg, _) = macro_call.token_tree().and_then(mbe::ast_to_token_tree)?; 102 let (macro_arg, _) = macro_call.token_tree().and_then(mbe::ast_to_token_tree)?;
102 103
103 let def_map = db.crate_def_map(loc.module.krate); 104 let macro_rules = macro_def_query(db, loc.def)?;
104 let (krate, macro_id) = def_map.resolve_macro(macro_call_id)?;
105 let def_map = db.crate_def_map(krate);
106 let macro_rules = &def_map[macro_id];
107 let tt = macro_rules.expand(&macro_arg).ok()?; 105 let tt = macro_rules.expand(&macro_arg).ok()?;
108 Some(mbe::token_tree_to_ast_item_list(&tt)) 106 Some(mbe::token_tree_to_ast_item_list(&tt))
109} 107}
@@ -126,6 +124,22 @@ impl From<MacroCallId> for HirFileId {
126 } 124 }
127} 125}
128 126
127#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
128pub(crate) enum MacroDefId {
129 MacroByExample { source_item_id: SourceItemId },
130}
131
132fn macro_def_query(db: &impl DefDatabase, id: MacroDefId) -> Option<Arc<MacroRules>> {
133 let syntax_node = match id {
134 MacroDefId::MacroByExample { source_item_id } => db.file_item(source_item_id),
135 };
136 let macro_call = ast::MacroCall::cast(&syntax_node).unwrap();
137 let arg = macro_call.token_tree()?;
138 let (tt, _) = mbe::ast_to_token_tree(arg)?;
139 let rules = MacroRules::parse(&tt).ok()?;
140 Some(Arc::new(rules))
141}
142
129/// `MacroCallId` identifies a particular macro invocation, like 143/// `MacroCallId` identifies a particular macro invocation, like
130/// `println!("Hello, {}", world)`. 144/// `println!("Hello, {}", world)`.
131#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 145#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -134,7 +148,7 @@ impl_arena_id!(MacroCallId);
134 148
135#[derive(Debug, Clone, PartialEq, Eq, Hash)] 149#[derive(Debug, Clone, PartialEq, Eq, Hash)]
136pub struct MacroCallLoc { 150pub struct MacroCallLoc {
137 pub(crate) module: Module, 151 pub(crate) def: MacroDefId,
138 pub(crate) source_item_id: SourceItemId, 152 pub(crate) source_item_id: SourceItemId,
139} 153}
140 154