feat(ast_codegen): support for generate_derive marker. (#4728)

Follow-on after #4276, related to #4284.
This commit is contained in:
rzvxa 2024-08-07 17:38:12 +00:00
parent 6a36616289
commit 2e91ad6c4e
3 changed files with 33 additions and 1 deletions

View file

@ -49,7 +49,7 @@ pub fn ast(_args: TokenStream, input: TokenStream) -> TokenStream {
/// Does not generate any code.
/// Only purpose is to allow using `#[scope]`, `#[visit]`, and other attrs in the AST node type defs.
/// These "marker" attributes are used in codegen.
#[proc_macro_derive(Ast, attributes(scope, visit, span, serde, tsify))]
#[proc_macro_derive(Ast, attributes(scope, visit, span, serde, tsify, generate_derive))]
pub fn ast_derive(_item: TokenStream) -> TokenStream {
TokenStream::new()
}

View file

@ -26,6 +26,15 @@ impl TypeDef {
pub fn visitable(&self) -> bool {
with_either!(self, it => it.visitable)
}
pub fn generated_derives(&self) -> &Vec<String> {
with_either!(self, it => &it.generated_derives)
}
pub fn generates_derive(&self, derive: &str) -> bool {
let generated_derives = self.generated_derives();
generated_derives.iter().any(|it| it == derive)
}
}
#[derive(Debug, Serialize)]
@ -41,6 +50,7 @@ pub struct StructDef {
pub size_32: usize,
pub align_32: usize,
pub offsets_32: Option<Vec<usize>>,
pub generated_derives: Vec<String>,
#[serde(skip)]
pub markers: OuterMarkers,
}
@ -60,6 +70,7 @@ pub struct EnumDef {
pub size_32: usize,
pub align_32: usize,
pub offsets_32: Option<Vec<usize>>,
pub generated_derives: Vec<String>,
}
impl EnumDef {

View file

@ -148,6 +148,8 @@ fn lower_ast_enum(it @ rust::Enum { item, meta }: &rust::Enum, ctx: &crate::Earl
size_32,
align_32,
offsets_32,
generated_derives: parse_generate_derive(&item.attrs),
}
}
@ -178,6 +180,8 @@ fn lower_ast_struct(
align_32,
offsets_32,
markers: parse_outer_markers(&item.attrs).unwrap(),
generated_derives: parse_generate_derive(&item.attrs),
}
}
@ -264,6 +268,23 @@ fn get_docs(attrs: &[syn::Attribute]) -> Vec<String> {
.collect()
}
fn parse_generate_derive(attrs: &[syn::Attribute]) -> Vec<String> {
let mut derives = std::collections::HashSet::new();
for attr in attrs {
if !attr.path().is_ident("generate_derive") {
continue;
}
let args: syn::punctuated::Punctuated<syn::Ident, syn::Token![,]> =
attr.parse_args_with(syn::punctuated::Punctuated::parse_terminated).unwrap();
for arg in args {
derives.insert(arg.to_string());
}
}
Vec::from_iter(derives)
}
macro_rules! with_either {
($def:expr, $it:ident => $body:expr) => {
match $def {