72 lines
2.6 KiB
Rust
72 lines
2.6 KiB
Rust
|
//! Nameres-specific procedural macro data and helpers.
|
||
|
|
||
|
use hir_expand::name::{AsName, Name};
|
||
|
use tt::{Leaf, TokenTree};
|
||
|
|
||
|
use crate::attr::Attrs;
|
||
|
|
||
|
#[derive(Debug, PartialEq, Eq)]
|
||
|
pub(super) struct ProcMacroDef {
|
||
|
pub(super) name: Name,
|
||
|
pub(super) kind: ProcMacroKind,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug, PartialEq, Eq)]
|
||
|
pub(super) enum ProcMacroKind {
|
||
|
CustomDerive { helpers: Box<[Name]> },
|
||
|
FnLike,
|
||
|
Attr,
|
||
|
}
|
||
|
|
||
|
impl Attrs {
|
||
|
#[rustfmt::skip]
|
||
|
pub(super) fn parse_proc_macro_decl(&self, func_name: &Name) -> Option<ProcMacroDef> {
|
||
|
if self.by_key("proc_macro").exists() {
|
||
|
Some(ProcMacroDef { name: func_name.clone(), kind: ProcMacroKind::FnLike })
|
||
|
} else if self.by_key("proc_macro_attribute").exists() {
|
||
|
Some(ProcMacroDef { name: func_name.clone(), kind: ProcMacroKind::Attr })
|
||
|
} else if self.by_key("proc_macro_derive").exists() {
|
||
|
let derive = self.by_key("proc_macro_derive").tt_values().next().unwrap();
|
||
|
|
||
|
match &*derive.token_trees {
|
||
|
// `#[proc_macro_derive(Trait)]`
|
||
|
[TokenTree::Leaf(Leaf::Ident(trait_name))] => Some(ProcMacroDef {
|
||
|
name: trait_name.as_name(),
|
||
|
kind: ProcMacroKind::CustomDerive { helpers: Box::new([]) },
|
||
|
}),
|
||
|
|
||
|
// `#[proc_macro_derive(Trait, attibutes(helper1, helper2, ...))]`
|
||
|
[
|
||
|
TokenTree::Leaf(Leaf::Ident(trait_name)),
|
||
|
TokenTree::Leaf(Leaf::Punct(comma)),
|
||
|
TokenTree::Leaf(Leaf::Ident(attributes)),
|
||
|
TokenTree::Subtree(helpers)
|
||
|
] if comma.char == ',' && attributes.text == "attributes" =>
|
||
|
{
|
||
|
let helpers = helpers.token_trees.iter()
|
||
|
.filter(|tt| !matches!(tt, TokenTree::Leaf(Leaf::Punct(comma)) if comma.char == ','))
|
||
|
.map(|tt| {
|
||
|
match tt {
|
||
|
TokenTree::Leaf(Leaf::Ident(helper)) => Some(helper.as_name()),
|
||
|
_ => None
|
||
|
}
|
||
|
})
|
||
|
.collect::<Option<Box<[_]>>>()?;
|
||
|
|
||
|
Some(ProcMacroDef {
|
||
|
name: trait_name.as_name(),
|
||
|
kind: ProcMacroKind::CustomDerive { helpers },
|
||
|
})
|
||
|
}
|
||
|
|
||
|
_ => {
|
||
|
log::trace!("malformed `#[proc_macro_derive]`: {}", derive);
|
||
|
None
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
None
|
||
|
}
|
||
|
}
|
||
|
}
|