diff options
Diffstat (limited to 'crates/hir_expand/src/db.rs')
-rw-r--r-- | crates/hir_expand/src/db.rs | 58 |
1 files changed, 35 insertions, 23 deletions
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index d672f6723..10fe60821 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use base_db::{salsa, SourceDatabase}; | 5 | use base_db::{salsa, SourceDatabase}; |
6 | use mbe::{ExpandError, ExpandResult, MacroRules}; | 6 | use mbe::{ExpandError, ExpandResult, MacroDef, MacroRules}; |
7 | use parser::FragmentKind; | 7 | use parser::FragmentKind; |
8 | use syntax::{ | 8 | use syntax::{ |
9 | algo::diff, | 9 | algo::diff, |
@@ -28,6 +28,7 @@ const TOKEN_LIMIT: usize = 524288; | |||
28 | #[derive(Debug, Clone, Eq, PartialEq)] | 28 | #[derive(Debug, Clone, Eq, PartialEq)] |
29 | pub enum TokenExpander { | 29 | pub enum TokenExpander { |
30 | MacroRules(mbe::MacroRules), | 30 | MacroRules(mbe::MacroRules), |
31 | MacroDef(mbe::MacroDef), | ||
31 | Builtin(BuiltinFnLikeExpander), | 32 | Builtin(BuiltinFnLikeExpander), |
32 | BuiltinDerive(BuiltinDeriveExpander), | 33 | BuiltinDerive(BuiltinDeriveExpander), |
33 | ProcMacro(ProcMacroExpander), | 34 | ProcMacro(ProcMacroExpander), |
@@ -42,6 +43,7 @@ impl TokenExpander { | |||
42 | ) -> mbe::ExpandResult<tt::Subtree> { | 43 | ) -> mbe::ExpandResult<tt::Subtree> { |
43 | match self { | 44 | match self { |
44 | TokenExpander::MacroRules(it) => it.expand(tt), | 45 | TokenExpander::MacroRules(it) => it.expand(tt), |
46 | TokenExpander::MacroDef(it) => it.expand(tt), | ||
45 | TokenExpander::Builtin(it) => it.expand(db, id, tt), | 47 | TokenExpander::Builtin(it) => it.expand(db, id, tt), |
46 | // FIXME switch these to ExpandResult as well | 48 | // FIXME switch these to ExpandResult as well |
47 | TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), | 49 | TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), |
@@ -57,6 +59,7 @@ impl TokenExpander { | |||
57 | pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId { | 59 | pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId { |
58 | match self { | 60 | match self { |
59 | TokenExpander::MacroRules(it) => it.map_id_down(id), | 61 | TokenExpander::MacroRules(it) => it.map_id_down(id), |
62 | TokenExpander::MacroDef(it) => it.map_id_down(id), | ||
60 | TokenExpander::Builtin(..) => id, | 63 | TokenExpander::Builtin(..) => id, |
61 | TokenExpander::BuiltinDerive(..) => id, | 64 | TokenExpander::BuiltinDerive(..) => id, |
62 | TokenExpander::ProcMacro(..) => id, | 65 | TokenExpander::ProcMacro(..) => id, |
@@ -66,6 +69,7 @@ impl TokenExpander { | |||
66 | pub fn map_id_up(&self, id: tt::TokenId) -> (tt::TokenId, mbe::Origin) { | 69 | pub fn map_id_up(&self, id: tt::TokenId) -> (tt::TokenId, mbe::Origin) { |
67 | match self { | 70 | match self { |
68 | TokenExpander::MacroRules(it) => it.map_id_up(id), | 71 | TokenExpander::MacroRules(it) => it.map_id_up(id), |
72 | TokenExpander::MacroDef(it) => it.map_id_up(id), | ||
69 | TokenExpander::Builtin(..) => (id, mbe::Origin::Call), | 73 | TokenExpander::Builtin(..) => (id, mbe::Origin::Call), |
70 | TokenExpander::BuiltinDerive(..) => (id, mbe::Origin::Call), | 74 | TokenExpander::BuiltinDerive(..) => (id, mbe::Origin::Call), |
71 | TokenExpander::ProcMacro(..) => (id, mbe::Origin::Call), | 75 | TokenExpander::ProcMacro(..) => (id, mbe::Origin::Call), |
@@ -115,7 +119,7 @@ pub fn expand_hypothetical( | |||
115 | token_to_map: syntax::SyntaxToken, | 119 | token_to_map: syntax::SyntaxToken, |
116 | ) -> Option<(SyntaxNode, syntax::SyntaxToken)> { | 120 | ) -> Option<(SyntaxNode, syntax::SyntaxToken)> { |
117 | let macro_file = MacroFile { macro_call_id: actual_macro_call }; | 121 | let macro_file = MacroFile { macro_call_id: actual_macro_call }; |
118 | let (tt, tmap_1) = mbe::syntax_node_to_token_tree(hypothetical_args.syntax()).unwrap(); | 122 | let (tt, tmap_1) = mbe::syntax_node_to_token_tree(hypothetical_args.syntax()); |
119 | let range = | 123 | let range = |
120 | token_to_map.text_range().checked_sub(hypothetical_args.syntax().text_range().start())?; | 124 | token_to_map.text_range().checked_sub(hypothetical_args.syntax().text_range().start())?; |
121 | let token_id = tmap_1.token_by_range(range)?; | 125 | let token_id = tmap_1.token_by_range(range)?; |
@@ -136,26 +140,34 @@ fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> { | |||
136 | 140 | ||
137 | fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { | 141 | fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { |
138 | match id.kind { | 142 | match id.kind { |
139 | MacroDefKind::Declarative(ast_id) => { | 143 | MacroDefKind::Declarative(ast_id) => match ast_id.to_node(db) { |
140 | let macro_rules = match ast_id.to_node(db) { | 144 | syntax::ast::Macro::MacroRules(macro_rules) => { |
141 | syntax::ast::Macro::MacroRules(mac) => mac, | 145 | let arg = macro_rules.token_tree()?; |
142 | syntax::ast::Macro::MacroDef(_) => return None, | 146 | let (tt, tmap) = mbe::ast_to_token_tree(&arg); |
143 | }; | 147 | let rules = match MacroRules::parse(&tt) { |
144 | let arg = macro_rules.token_tree()?; | 148 | Ok(it) => it, |
145 | let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| { | 149 | Err(err) => { |
146 | log::warn!("fail on macro_def to token tree: {:#?}", arg); | 150 | let name = macro_rules.name().map(|n| n.to_string()).unwrap_or_default(); |
147 | None | 151 | log::warn!("fail on macro_def parse ({}): {:?} {:#?}", name, err, tt); |
148 | })?; | 152 | return None; |
149 | let rules = match MacroRules::parse(&tt) { | 153 | } |
150 | Ok(it) => it, | 154 | }; |
151 | Err(err) => { | 155 | Some(Arc::new((TokenExpander::MacroRules(rules), tmap))) |
152 | let name = macro_rules.name().map(|n| n.to_string()).unwrap_or_default(); | 156 | } |
153 | log::warn!("fail on macro_def parse ({}): {:?} {:#?}", name, err, tt); | 157 | syntax::ast::Macro::MacroDef(macro_def) => { |
154 | return None; | 158 | let arg = macro_def.body()?; |
155 | } | 159 | let (tt, tmap) = mbe::ast_to_token_tree(&arg); |
156 | }; | 160 | let rules = match MacroDef::parse(&tt) { |
157 | Some(Arc::new((TokenExpander::MacroRules(rules), tmap))) | 161 | Ok(it) => it, |
158 | } | 162 | Err(err) => { |
163 | let name = macro_def.name().map(|n| n.to_string()).unwrap_or_default(); | ||
164 | log::warn!("fail on macro_def parse ({}): {:?} {:#?}", name, err, tt); | ||
165 | return None; | ||
166 | } | ||
167 | }; | ||
168 | Some(Arc::new((TokenExpander::MacroDef(rules), tmap))) | ||
169 | } | ||
170 | }, | ||
159 | MacroDefKind::BuiltIn(expander, _) => { | 171 | MacroDefKind::BuiltIn(expander, _) => { |
160 | Some(Arc::new((TokenExpander::Builtin(expander), mbe::TokenMap::default()))) | 172 | Some(Arc::new((TokenExpander::Builtin(expander), mbe::TokenMap::default()))) |
161 | } | 173 | } |
@@ -184,7 +196,7 @@ fn macro_arg_text(db: &dyn AstDatabase, id: MacroCallId) -> Option<GreenNode> { | |||
184 | 196 | ||
185 | fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { | 197 | fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { |
186 | let arg = db.macro_arg_text(id)?; | 198 | let arg = db.macro_arg_text(id)?; |
187 | let (tt, tmap) = mbe::syntax_node_to_token_tree(&SyntaxNode::new_root(arg))?; | 199 | let (tt, tmap) = mbe::syntax_node_to_token_tree(&SyntaxNode::new_root(arg)); |
188 | Some(Arc::new((tt, tmap))) | 200 | Some(Arc::new((tt, tmap))) |
189 | } | 201 | } |
190 | 202 | ||