1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 //! Proc Macro Expander stub use base_db::{CrateId, ProcMacroExpansionError, ProcMacroId, ProcMacroKind}; use crate::{db::AstDatabase, ExpandError, ExpandResult}; #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] pub struct ProcMacroExpander { krate: CrateId, proc_macro_id: Option<ProcMacroId>, } impl ProcMacroExpander { pub fn new(krate: CrateId, proc_macro_id: ProcMacroId) -> Self { Self { krate, proc_macro_id: Some(proc_macro_id) } } pub fn dummy(krate: CrateId) -> Self { // FIXME: Should store the name for better errors Self { krate, proc_macro_id: None } } pub fn is_dummy(&self) -> bool { self.proc_macro_id.is_none() } pub fn expand( self, db: &dyn AstDatabase, calling_crate: CrateId, tt: &tt::Subtree, attr_arg: Option<&tt::Subtree>, ) -> ExpandResult<tt::Subtree> { match self.proc_macro_id { Some(id) => { let krate_graph = db.crate_graph(); let proc_macro = match krate_graph[self.krate].proc_macro.get(id.0 as usize) { Some(proc_macro) => proc_macro, None => { return ExpandResult::only_err(ExpandError::Other( "No proc-macro found.".into(), )) } }; // Proc macros have access to the environment variables of the invoking crate. let env = &krate_graph[calling_crate].env; match proc_macro.expander.expand(tt, attr_arg, env) { Ok(t) => ExpandResult::ok(t), Err(err) => match err { // Don't discard the item in case something unexpected happened while expanding attributes ProcMacroExpansionError::System(text) if proc_macro.kind == ProcMacroKind::Attr => { ExpandResult { value: tt.clone(), err: Some(ExpandError::Other(text.into())), } } ProcMacroExpansionError::System(text) | ProcMacroExpansionError::Panic(text) => { ExpandResult::only_err(ExpandError::Other(text.into())) } }, } } None => ExpandResult::only_err(ExpandError::UnresolvedProcMacro), } } }