Refactor macro handling: add pascal_to_snake utility, rewrite Target handling, and update descriptor structure for bits-based targets.
This commit is contained in:
@@ -3,6 +3,22 @@ use proc_macro2::TokenStream as TokenStream2;
|
||||
|
||||
use crate::attrs::MacroInput;
|
||||
|
||||
fn rewrite_bitor_target_expr(expr: syn::Expr) -> syn::Expr
|
||||
{
|
||||
match expr
|
||||
{
|
||||
syn::Expr::Binary(mut bin) if matches!(bin.op, syn::BinOp::BitOr(_)) => {
|
||||
bin.left = Box::new(rewrite_bitor_target_expr(*bin.left));
|
||||
bin.right = Box::new(rewrite_bitor_target_expr(*bin.right));
|
||||
syn::Expr::Binary(bin)
|
||||
}
|
||||
|
||||
other => {
|
||||
syn::parse_quote! { (#other).bits() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expand(parsed: MacroInput) -> syn::Result<TokenStream2>
|
||||
{
|
||||
let struct_ident = &parsed.ident;
|
||||
@@ -16,8 +32,8 @@ pub fn expand(parsed: MacroInput) -> syn::Result<TokenStream2>
|
||||
.unwrap_or_else(|| struct_ident.to_string());
|
||||
|
||||
let target_expr: syn::Expr = parsed.target
|
||||
.map(|e| e.0)
|
||||
.unwrap_or_else(|| syn::parse_quote! { ::pmp_macro_misc::Target::ALL });
|
||||
.map(|e| rewrite_bitor_target_expr(e.0))
|
||||
.unwrap_or_else(|| syn::parse_quote! { ::pmp_macro::Target::ALL.bits() });
|
||||
|
||||
let docs: String = parsed.docs.map(|s| s.0).unwrap_or_default();
|
||||
|
||||
@@ -53,7 +69,7 @@ pub fn expand(parsed: MacroInput) -> syn::Result<TokenStream2>
|
||||
};
|
||||
|
||||
param_tokens.push(quote_spanned! { span =>
|
||||
::pmp_macro_misc::ParamDescriptor {
|
||||
::pmp_macro::ParamDescriptor {
|
||||
name: #field_name,
|
||||
php_type: #php_type,
|
||||
required: #required,
|
||||
@@ -64,47 +80,48 @@ pub fn expand(parsed: MacroInput) -> syn::Result<TokenStream2>
|
||||
|
||||
if let Some(e) = errors { return Err(e); }
|
||||
|
||||
let mod_ident = format_ident!("__pmp_macro_impl_{}", struct_ident);
|
||||
let handler = quote! { super::#struct_ident };
|
||||
let snaked_ident = pmp_core::pascal_to_snake(struct_ident.to_string().as_str());
|
||||
let mod_ident = format_ident!("__pmp_macro_impl_{}", snaked_ident);
|
||||
let handler = quote! { super::#struct_ident };
|
||||
|
||||
Ok(quote!
|
||||
{
|
||||
#[doc(hidden)]
|
||||
mod #mod_ident
|
||||
{
|
||||
use ::pmp_macro_misc::{
|
||||
AnalyzeFn, MacroDescriptor, MacroRegistration, ParamDescriptor,
|
||||
TransformFn, PmpMacro,
|
||||
use ::pmp_macro::{
|
||||
AnalyzeFn, MacroDescriptor, MacroRegistration,
|
||||
ParamDescriptor, Target, TransformFn, PmpMacro,
|
||||
};
|
||||
|
||||
static PARAMS: &[ParamDescriptor] = &[ #(#param_tokens),* ];
|
||||
|
||||
static DESCRIPTOR: MacroDescriptor = MacroDescriptor {
|
||||
name: #attr_name,
|
||||
target: #target_expr,
|
||||
docs: #docs,
|
||||
params: PARAMS,
|
||||
name: #attr_name,
|
||||
target_bits: #target_expr,
|
||||
docs: #docs,
|
||||
params: PARAMS,
|
||||
};
|
||||
|
||||
fn analyze(
|
||||
ctx: &::pmp_macro_misc::MacroContext,
|
||||
attr: &::pmp_macro_misc::ResolvedAttr,
|
||||
node: &::pmp_macro_misc::AttributedNode,
|
||||
) -> ::std::vec::Vec<::pmp_macro_misc::Diagnostic>
|
||||
ctx: &::pmp_macro::MacroContext,
|
||||
attr: &::pmp_macro::ResolvedAttr,
|
||||
node: &::pmp_macro::AttributedNode,
|
||||
) -> ::std::vec::Vec<::pmp_macro::Diagnostic>
|
||||
{
|
||||
<#handler as PmpMacro>::analyze(&::std::default::Default::default(), ctx, attr, node)
|
||||
}
|
||||
|
||||
fn transform(
|
||||
ctx: &::pmp_macro_misc::MacroContext,
|
||||
attr: &::pmp_macro_misc::ResolvedAttr,
|
||||
node: &::pmp_macro_misc::AttributedNode,
|
||||
) -> ::std::vec::Vec<::pmp_macro_misc::Rewrite>
|
||||
ctx: &::pmp_macro::MacroContext,
|
||||
attr: &::pmp_macro::ResolvedAttr,
|
||||
node: &::pmp_macro::AttributedNode,
|
||||
) -> ::std::vec::Vec<::pmp_macro::Rewrite>
|
||||
{
|
||||
<#handler as PmpMacro>::transform(&::std::default::Default::default(), ctx, attr, node)
|
||||
}
|
||||
|
||||
::inventory::submit! {
|
||||
::pmp_macro::inventory::submit! {
|
||||
MacroRegistration::new(&DESCRIPTOR, analyze, transform)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,26 @@
|
||||
use crate::target::Target;
|
||||
|
||||
/// Describes a single constructor parameter of a PHP macro attribute.
|
||||
///
|
||||
/// All fields are `&'static str` so the descriptor can be embedded as a
|
||||
/// `static` and referenced from the inventory without allocation.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct ParamDescriptor {
|
||||
/// The parameter name as it appears in the PHP constructor.
|
||||
pub name: &'static str,
|
||||
/// A human-readable PHP type hint, e.g. `"class-string[]"` or `"bool"`.
|
||||
pub php_type: &'static str,
|
||||
/// Whether the parameter must be supplied by the caller.
|
||||
pub required: bool,
|
||||
/// The PHP source representation of the default value, e.g. `"[]"` or `"false"`.
|
||||
/// `None` when `required` is `true`.
|
||||
pub default: Option<&'static str>,
|
||||
}
|
||||
|
||||
/// Static metadata for a registered PHP macro attribute.
|
||||
///
|
||||
/// Generated by `#[derive(PmpMacro)]` and stored as a `&'static MacroDescriptor`
|
||||
/// in the inventory. Entirely allocation-free.
|
||||
#[derive(Debug)]
|
||||
pub struct MacroDescriptor {
|
||||
/// The PHP attribute name, e.g. `"Sealed"`. Used to match against
|
||||
/// attribute usages in parsed PHP files.
|
||||
pub name: &'static str,
|
||||
/// Which PHP constructs this attribute is permitted to annotate.
|
||||
pub target: Target,
|
||||
/// Human-readable description of what this macro does.
|
||||
/// Used for error messages and generated documentation.
|
||||
pub docs: &'static str,
|
||||
/// The constructor parameters this attribute accepts.
|
||||
pub params: &'static [ParamDescriptor],
|
||||
pub name: &'static str,
|
||||
/// Raw bitflags value - use `.target()` to get a `Target`.
|
||||
/// Stored as `u16` so the static initializer remains `const`.
|
||||
pub target_bits: u16,
|
||||
pub docs: &'static str,
|
||||
pub params: &'static [ParamDescriptor],
|
||||
}
|
||||
|
||||
impl MacroDescriptor
|
||||
{
|
||||
pub fn target(&self) -> Target {
|
||||
Target::from_bits_truncate(self.target_bits)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,10 @@ mod traits;
|
||||
mod context;
|
||||
mod descriptor;
|
||||
|
||||
pub use target::Target;
|
||||
pub use descriptor::{ MacroDescriptor, ParamDescriptor };
|
||||
pub use traits::{ PmpMacro, MacroRegistry, MacroRegistration, };
|
||||
pub use context::{ Rewrite, ResolvedAttr, Diagnostic, MacroContext, AttributedNode };
|
||||
#[doc(hidden)]
|
||||
pub use inventory;
|
||||
|
||||
pub use target::*;
|
||||
pub use traits::*;
|
||||
pub use context::*;
|
||||
pub use descriptor::*;
|
||||
|
||||
Reference in New Issue
Block a user