From a193666361f6ea9725b927a35f5baf77da713c0a Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sat, 27 Mar 2021 13:44:54 +0800 Subject: Basic Support Macro 2.0 --- crates/hir_expand/src/db.rs | 60 ++++++++++++++++++++++++++-------------- crates/hir_expand/src/hygiene.rs | 2 +- crates/hir_expand/src/lib.rs | 2 +- 3 files changed, 41 insertions(+), 23 deletions(-) (limited to 'crates/hir_expand') diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index d672f6723..c0ab70b60 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use base_db::{salsa, SourceDatabase}; -use mbe::{ExpandError, ExpandResult, MacroRules}; +use mbe::{ExpandError, ExpandResult, MacroDef, MacroRules}; use parser::FragmentKind; use syntax::{ algo::diff, @@ -28,6 +28,7 @@ const TOKEN_LIMIT: usize = 524288; #[derive(Debug, Clone, Eq, PartialEq)] pub enum TokenExpander { MacroRules(mbe::MacroRules), + MacroDef(mbe::MacroDef), Builtin(BuiltinFnLikeExpander), BuiltinDerive(BuiltinDeriveExpander), ProcMacro(ProcMacroExpander), @@ -42,6 +43,7 @@ impl TokenExpander { ) -> mbe::ExpandResult { match self { TokenExpander::MacroRules(it) => it.expand(tt), + TokenExpander::MacroDef(it) => it.expand(tt), TokenExpander::Builtin(it) => it.expand(db, id, tt), // FIXME switch these to ExpandResult as well TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), @@ -57,6 +59,7 @@ impl TokenExpander { pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId { match self { TokenExpander::MacroRules(it) => it.map_id_down(id), + TokenExpander::MacroDef(it) => it.map_id_down(id), TokenExpander::Builtin(..) => id, TokenExpander::BuiltinDerive(..) => id, TokenExpander::ProcMacro(..) => id, @@ -66,6 +69,7 @@ impl TokenExpander { pub fn map_id_up(&self, id: tt::TokenId) -> (tt::TokenId, mbe::Origin) { match self { TokenExpander::MacroRules(it) => it.map_id_up(id), + TokenExpander::MacroDef(it) => it.map_id_up(id), TokenExpander::Builtin(..) => (id, mbe::Origin::Call), TokenExpander::BuiltinDerive(..) => (id, mbe::Origin::Call), TokenExpander::ProcMacro(..) => (id, mbe::Origin::Call), @@ -136,26 +140,40 @@ fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc { fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option> { match id.kind { - MacroDefKind::Declarative(ast_id) => { - let macro_rules = match ast_id.to_node(db) { - syntax::ast::Macro::MacroRules(mac) => mac, - syntax::ast::Macro::MacroDef(_) => return None, - }; - let arg = macro_rules.token_tree()?; - let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| { - log::warn!("fail on macro_def to token tree: {:#?}", arg); - None - })?; - let rules = match MacroRules::parse(&tt) { - Ok(it) => it, - Err(err) => { - let name = macro_rules.name().map(|n| n.to_string()).unwrap_or_default(); - log::warn!("fail on macro_def parse ({}): {:?} {:#?}", name, err, tt); - return None; - } - }; - Some(Arc::new((TokenExpander::MacroRules(rules), tmap))) - } + MacroDefKind::Declarative(ast_id) => match ast_id.to_node(db) { + syntax::ast::Macro::MacroRules(macro_rules) => { + let arg = macro_rules.token_tree()?; + let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| { + log::warn!("fail on macro_rules to token tree: {:#?}", arg); + None + })?; + let rules = match MacroRules::parse(&tt) { + Ok(it) => it, + Err(err) => { + let name = macro_rules.name().map(|n| n.to_string()).unwrap_or_default(); + log::warn!("fail on macro_def parse ({}): {:?} {:#?}", name, err, tt); + return None; + } + }; + Some(Arc::new((TokenExpander::MacroRules(rules), tmap))) + } + syntax::ast::Macro::MacroDef(macro_def) => { + let arg = macro_def.body()?; + let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| { + log::warn!("fail on macro_def to token tree: {:#?}", arg); + None + })?; + let rules = match MacroDef::parse(&tt) { + Ok(it) => it, + Err(err) => { + let name = macro_def.name().map(|n| n.to_string()).unwrap_or_default(); + log::warn!("fail on macro_def parse ({}): {:?} {:#?}", name, err, tt); + return None; + } + }; + Some(Arc::new((TokenExpander::MacroDef(rules), tmap))) + } + }, MacroDefKind::BuiltIn(expander, _) => { Some(Arc::new((TokenExpander::Builtin(expander), mbe::TokenMap::default()))) } diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs index 0e0f7214a..779725629 100644 --- a/crates/hir_expand/src/hygiene.rs +++ b/crates/hir_expand/src/hygiene.rs @@ -148,7 +148,7 @@ fn make_hygiene_info( let def_offset = loc.def.ast_id().left().and_then(|id| { let def_tt = match id.to_node(db) { ast::Macro::MacroRules(mac) => mac.token_tree()?.syntax().text_range().start(), - ast::Macro::MacroDef(_) => return None, + ast::Macro::MacroDef(mac) => mac.body()?.syntax().text_range().start(), }; Some(InFile::new(id.file_id, def_tt)) }); diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs index b8045fda9..3e332ee47 100644 --- a/crates/hir_expand/src/lib.rs +++ b/crates/hir_expand/src/lib.rs @@ -151,7 +151,7 @@ impl HirFileId { let def = loc.def.ast_id().left().and_then(|id| { let def_tt = match id.to_node(db) { ast::Macro::MacroRules(mac) => mac.token_tree()?, - ast::Macro::MacroDef(_) => return None, + ast::Macro::MacroDef(mac) => mac.body()?, }; Some(InFile::new(id.file_id, def_tt)) }); -- cgit v1.2.3