Skip to content

Commit

Permalink
feat(macro): add outer macro for impls
Browse files Browse the repository at this point in the history
Refs: 335
  • Loading branch information
Xenira committed Nov 27, 2024
1 parent cfdd769 commit af115e7
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 94 deletions.
5 changes: 2 additions & 3 deletions crates/macros/src/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use syn::{Attribute, AttributeArgs, Expr, Fields, FieldsNamed, ItemStruct, LitSt

#[derive(Debug, Default)]
pub struct Class {
pub name: String,
pub class_name: String,
pub struct_path: String,
pub parent: Option<String>,
Expand Down Expand Up @@ -41,7 +40,7 @@ pub struct AttrArgs {
flags: Option<Expr>,
}

pub fn parser(args: AttributeArgs, mut input: ItemStruct) -> Result<(TokenStream, Class)> {
pub fn parser(args: AttributeArgs, mut input: ItemStruct) -> Result<(TokenStream, String, Class)> {
let args = AttrArgs::from_list(&args)
.map_err(|e| anyhow!("Unable to parse attribute arguments: {:?}", e))?;

Expand Down Expand Up @@ -125,7 +124,6 @@ pub fn parser(args: AttributeArgs, mut input: ItemStruct) -> Result<(TokenStream
let struct_path = ident.to_string();
let flags = args.flags.map(|flags| flags.to_token_stream().to_string());
let class = Class {
name: ident.to_string(),
class_name,
struct_path,
parent,
Expand All @@ -143,6 +141,7 @@ pub fn parser(args: AttributeArgs, mut input: ItemStruct) -> Result<(TokenStream

::ext_php_rs::class_derives!(#ident);
},
ident.to_string(),
class,
))
}
Expand Down
3 changes: 1 addition & 2 deletions crates/macros/src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,9 +457,8 @@ impl Function {
}
});

// TODO: fix module name
quote! {
::ext_php_rs::builders::FunctionBuilder::new(#name, module::#name_ident)
::ext_php_rs::builders::FunctionBuilder::new(#name, #name_ident)
#(#args)*
#output
.build()
Expand Down
61 changes: 30 additions & 31 deletions crates/macros/src/impl_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use quote::quote;
use std::collections::HashMap;
use syn::{Attribute, AttributeArgs, ItemImpl, Lit, Meta, NestedMeta};

use crate::class::Class;
use crate::helpers::get_docs;
use crate::{
class::{Property, PropertyAttr},
Expand Down Expand Up @@ -94,7 +95,11 @@ pub enum PropAttrTy {
Setter,
}

pub fn parser(args: AttributeArgs, input: ItemImpl) -> Result<TokenStream> {
pub fn parser(
args: AttributeArgs,
input: ItemImpl,
classes: &mut HashMap<String, Class>,
) -> Result<TokenStream> {
let args = AttrArgs::from_list(&args)
.map_err(|e| anyhow!("Unable to parse attribute arguments: {:?}", e))?;

Expand All @@ -105,29 +110,23 @@ pub fn parser(args: AttributeArgs, input: ItemImpl) -> Result<TokenStream> {
bail!("This macro cannot be used on trait implementations.");
}

// if state.startup_function.is_some() {
// bail!(
// "Impls must be declared before you declare your startup function and module function."
// );
// }
//
// let class = state.classes.get_mut(&class_name).ok_or_else(|| {
// anyhow!(
// "You must use `#[php_class]` on the struct before using this attribute on the impl."
// )
// })?;
let class = classes.get_mut(&class_name).ok_or_else(|| {
anyhow!(
"You must use `#[php_class]` on the struct before using this attribute on the impl."
)
})?;

let tokens = items
.into_iter()
.map(|item| {
Ok(match item {
syn::ImplItem::Const(constant) => {
// class.constants.push(Constant {
// name: constant.ident.to_string(),
// // visibility: Visibility::Public,
// docs: get_docs(&constant.attrs),
// value: constant.expr.to_token_stream().to_string(),
// });
class.constants.push(Constant {
name: constant.ident.to_string(),
// visibility: Visibility::Public,
docs: get_docs(&constant.attrs),
value: constant.expr.to_token_stream().to_string(),
});

quote! {
#[allow(dead_code)]
Expand All @@ -141,24 +140,24 @@ pub fn parser(args: AttributeArgs, input: ItemImpl) -> Result<TokenStream> {
// TODO(david): How do we handle comments for getter/setter? Take the comments
// from the methods??
if let Some((prop, ty)) = parsed_method.property {
// let prop = class
// .properties
// .entry(prop)
// .or_insert_with(|| Property::method(vec![], None));
let prop = class
.properties
.entry(prop)
.or_insert_with(|| Property::method(vec![], None));
let ident = parsed_method.method.orig_ident.clone();

// match ty {
// PropAttrTy::Getter => prop.add_getter(ident)?,
// PropAttrTy::Setter => prop.add_setter(ident)?,
// }
match ty {
PropAttrTy::Getter => prop.add_getter(ident)?,
PropAttrTy::Setter => prop.add_setter(ident)?,
}
}
if parsed_method.constructor {
// if class.constructor.is_some() {
// bail!("You cannot have two constructors on the same class.");
// }
// class.constructor = Some(parsed_method.method);
if class.constructor.is_some() {
bail!("You cannot have two constructors on the same class.");
}
class.constructor = Some(parsed_method.method);
} else {
// class.methods.push(parsed_method.method);
class.methods.push(parsed_method.method);
}
parsed_method.tokens
}
Expand Down
48 changes: 26 additions & 22 deletions crates/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,15 @@ mod startup_function;
mod syn_ext;
mod zval;

use std::{borrow::BorrowMut, collections::HashMap};
use std::collections::HashMap;

use constant::Constant;
use darling::FromMeta;
use proc_macro::TokenStream;
use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::{quote, ToTokens};
use syn::{
parse_macro_input, spanned::Spanned, Attribute, AttributeArgs, DeriveInput, Item, ItemConst,
ItemFn, ItemForeignMod, ItemImpl, ItemMod, ItemStruct, NestedMeta,
parse_macro_input, AttributeArgs, DeriveInput, ItemConst, ItemFn, ItemForeignMod, ItemMod,
NestedMeta,
};

extern crate proc_macro;
Expand All @@ -32,7 +31,6 @@ struct State {
functions: Vec<function::Function>,
classes: HashMap<String, class::Class>,
constants: Vec<Constant>,
startup_function: Option<String>,
}

impl State {
Expand All @@ -55,15 +53,18 @@ impl State {
}

#[proc_macro_attribute]
pub fn php_class(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as AttributeArgs);
let input = parse_macro_input!(input as ItemStruct);

match class::parser(args, input) {
Ok((parsed, _)) => parsed,
Err(e) => syn::Error::new(Span::call_site(), e).to_compile_error(),
}
.into()
pub fn php_class(_args: TokenStream, _input: TokenStream) -> TokenStream {
// let args = parse_macro_input!(args as AttributeArgs);
// let input = parse_macro_input!(input as ItemStruct);
//
// match class::parser(args, input) {
// Ok((parsed, _)) => parsed,
// Err(e) => syn::Error::new(Span::call_site(), e).to_compile_error(),
// }
// .into()
syn::Error::new(Span::call_site(), "php_class is not supported")
.to_compile_error()
.into()
}

#[proc_macro_attribute]
Expand Down Expand Up @@ -114,14 +115,17 @@ pub fn php_startup(args: TokenStream, input: TokenStream) -> TokenStream {

#[proc_macro_attribute]
pub fn php_impl(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as AttributeArgs);
let input = parse_macro_input!(input as ItemImpl);

match impl_::parser(args, input) {
Ok(parsed) => parsed,
Err(e) => syn::Error::new(Span::call_site(), e).to_compile_error(),
}
.into()
// let args = parse_macro_input!(args as AttributeArgs);
// let input = parse_macro_input!(input as ItemImpl);
//
// match impl_::parser(args, input) {
// Ok(parsed) => parsed,
// Err(e) => syn::Error::new(Span::call_site(), e).to_compile_error(),
// }
// .into()
syn::Error::new(Span::call_site(), "php_impl is not supported")
.to_compile_error()
.into()
}

#[proc_macro_attribute]
Expand Down
10 changes: 10 additions & 0 deletions crates/macros/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ pub fn parser(input: ItemMod) -> Result<TokenStream> {
continue;
}
}
Item::Impl(i) => {
if i.attrs
.iter()
.find(|a| a.path.is_ident("php_impl"))
.is_some()
{
builder.add_implementation(i.clone());
continue;
}
}
_ => {}
}
builder.add_unmapped(item.clone());
Expand Down
Loading

0 comments on commit af115e7

Please sign in to comment.