diff options
author | Aleksey Kladov <[email protected]> | 2019-03-26 10:09:39 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-03-26 10:20:54 +0000 |
commit | 5270bca5f72fa65f0515be776e06d3d6a4d1efca (patch) | |
tree | fa1b8b8ac66713ba29b676e1c2fdd4c4357f24ff /crates/ra_hir/src/ids.rs | |
parent | dc94f3612583c5e960b334761ad0c18d328840ea (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.rs | 24 |
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::{ | |||
7 | use ra_db::{LocationInterner, FileId}; | 7 | use ra_db::{LocationInterner, FileId}; |
8 | use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, SyntaxNodePtr, ast}; | 8 | use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, SyntaxNodePtr, ast}; |
9 | use ra_arena::{Arena, RawId, ArenaId, impl_arena_id}; | 9 | use ra_arena::{Arena, RawId, ArenaId, impl_arena_id}; |
10 | use mbe::MacroRules; | ||
10 | 11 | ||
11 | use crate::{ | 12 | use 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(¯o_arg).ok()?; | 105 | let tt = macro_rules.expand(¯o_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)] | ||
128 | pub(crate) enum MacroDefId { | ||
129 | MacroByExample { source_item_id: SourceItemId }, | ||
130 | } | ||
131 | |||
132 | fn 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)] |
136 | pub struct MacroCallLoc { | 150 | pub 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 | ||