Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-expand/src/proc_macro.rs')
| -rw-r--r-- | crates/hir-expand/src/proc_macro.rs | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/crates/hir-expand/src/proc_macro.rs b/crates/hir-expand/src/proc_macro.rs new file mode 100644 index 0000000000..df6c38761c --- /dev/null +++ b/crates/hir-expand/src/proc_macro.rs @@ -0,0 +1,70 @@ +//! 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), + } + } +} |