Skip to content

Commit 3f3c5b0

Browse files
committed
feat(macro): add outer macro for impls
Refs: 335
1 parent 1728c1c commit 3f3c5b0

File tree

7 files changed

+129
-94
lines changed

7 files changed

+129
-94
lines changed

crates/macros/src/class.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use syn::{Attribute, AttributeArgs, Expr, Fields, FieldsNamed, ItemStruct, LitSt
99

1010
#[derive(Debug, Default)]
1111
pub struct Class {
12-
pub name: String,
1312
pub class_name: String,
1413
pub struct_path: String,
1514
pub parent: Option<String>,
@@ -41,7 +40,7 @@ pub struct AttrArgs {
4140
flags: Option<Expr>,
4241
}
4342

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

@@ -125,7 +124,6 @@ pub fn parser(args: AttributeArgs, mut input: ItemStruct) -> Result<(TokenStream
125124
let struct_path = ident.to_string();
126125
let flags = args.flags.map(|flags| flags.to_token_stream().to_string());
127126
let class = Class {
128-
name: ident.to_string(),
129127
class_name,
130128
struct_path,
131129
parent,
@@ -143,6 +141,7 @@ pub fn parser(args: AttributeArgs, mut input: ItemStruct) -> Result<(TokenStream
143141

144142
::ext_php_rs::class_derives!(#ident);
145143
},
144+
ident.to_string(),
146145
class,
147146
))
148147
}

crates/macros/src/function.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,9 +457,8 @@ impl Function {
457457
}
458458
});
459459

460-
// TODO: fix module name
461460
quote! {
462-
::ext_php_rs::builders::FunctionBuilder::new(#name, module::#name_ident)
461+
::ext_php_rs::builders::FunctionBuilder::new(#name, #name_ident)
463462
#(#args)*
464463
#output
465464
.build()

crates/macros/src/impl_.rs

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use quote::quote;
55
use std::collections::HashMap;
66
use syn::{Attribute, AttributeArgs, ItemImpl, Lit, Meta, NestedMeta};
77

8+
use crate::class::Class;
89
use crate::helpers::get_docs;
910
use crate::{
1011
class::{Property, PropertyAttr},
@@ -94,7 +95,11 @@ pub enum PropAttrTy {
9495
Setter,
9596
}
9697

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

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

108-
// if state.startup_function.is_some() {
109-
// bail!(
110-
// "Impls must be declared before you declare your startup function and module function."
111-
// );
112-
// }
113-
//
114-
// let class = state.classes.get_mut(&class_name).ok_or_else(|| {
115-
// anyhow!(
116-
// "You must use `#[php_class]` on the struct before using this attribute on the impl."
117-
// )
118-
// })?;
113+
let class = classes.get_mut(&class_name).ok_or_else(|| {
114+
anyhow!(
115+
"You must use `#[php_class]` on the struct before using this attribute on the impl."
116+
)
117+
})?;
119118

120119
let tokens = items
121120
.into_iter()
122121
.map(|item| {
123122
Ok(match item {
124123
syn::ImplItem::Const(constant) => {
125-
// class.constants.push(Constant {
126-
// name: constant.ident.to_string(),
127-
// // visibility: Visibility::Public,
128-
// docs: get_docs(&constant.attrs),
129-
// value: constant.expr.to_token_stream().to_string(),
130-
// });
124+
class.constants.push(Constant {
125+
name: constant.ident.to_string(),
126+
// visibility: Visibility::Public,
127+
docs: get_docs(&constant.attrs),
128+
value: constant.expr.to_token_stream().to_string(),
129+
});
131130

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

150-
// match ty {
151-
// PropAttrTy::Getter => prop.add_getter(ident)?,
152-
// PropAttrTy::Setter => prop.add_setter(ident)?,
153-
// }
149+
match ty {
150+
PropAttrTy::Getter => prop.add_getter(ident)?,
151+
PropAttrTy::Setter => prop.add_setter(ident)?,
152+
}
154153
}
155154
if parsed_method.constructor {
156-
// if class.constructor.is_some() {
157-
// bail!("You cannot have two constructors on the same class.");
158-
// }
159-
// class.constructor = Some(parsed_method.method);
155+
if class.constructor.is_some() {
156+
bail!("You cannot have two constructors on the same class.");
157+
}
158+
class.constructor = Some(parsed_method.method);
160159
} else {
161-
// class.methods.push(parsed_method.method);
160+
class.methods.push(parsed_method.method);
162161
}
163162
parsed_method.tokens
164163
}

crates/macros/src/lib.rs

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,15 @@ mod startup_function;
1313
mod syn_ext;
1414
mod zval;
1515

16-
use std::{borrow::BorrowMut, collections::HashMap};
16+
use std::collections::HashMap;
1717

1818
use constant::Constant;
1919
use darling::FromMeta;
2020
use proc_macro::TokenStream;
2121
use proc_macro2::{Span, TokenStream as TokenStream2};
22-
use quote::{quote, ToTokens};
2322
use syn::{
24-
parse_macro_input, spanned::Spanned, Attribute, AttributeArgs, DeriveInput, Item, ItemConst,
25-
ItemFn, ItemForeignMod, ItemImpl, ItemMod, ItemStruct, NestedMeta,
23+
parse_macro_input, AttributeArgs, DeriveInput, ItemConst, ItemFn, ItemForeignMod, ItemMod,
24+
NestedMeta,
2625
};
2726

2827
extern crate proc_macro;
@@ -32,7 +31,6 @@ struct State {
3231
functions: Vec<function::Function>,
3332
classes: HashMap<String, class::Class>,
3433
constants: Vec<Constant>,
35-
startup_function: Option<String>,
3634
}
3735

3836
impl State {
@@ -55,15 +53,18 @@ impl State {
5553
}
5654

5755
#[proc_macro_attribute]
58-
pub fn php_class(args: TokenStream, input: TokenStream) -> TokenStream {
59-
let args = parse_macro_input!(args as AttributeArgs);
60-
let input = parse_macro_input!(input as ItemStruct);
61-
62-
match class::parser(args, input) {
63-
Ok((parsed, _)) => parsed,
64-
Err(e) => syn::Error::new(Span::call_site(), e).to_compile_error(),
65-
}
66-
.into()
56+
pub fn php_class(_args: TokenStream, _input: TokenStream) -> TokenStream {
57+
// let args = parse_macro_input!(args as AttributeArgs);
58+
// let input = parse_macro_input!(input as ItemStruct);
59+
//
60+
// match class::parser(args, input) {
61+
// Ok((parsed, _)) => parsed,
62+
// Err(e) => syn::Error::new(Span::call_site(), e).to_compile_error(),
63+
// }
64+
// .into()
65+
syn::Error::new(Span::call_site(), "php_class is not supported")
66+
.to_compile_error()
67+
.into()
6768
}
6869

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

115116
#[proc_macro_attribute]
116117
pub fn php_impl(args: TokenStream, input: TokenStream) -> TokenStream {
117-
let args = parse_macro_input!(args as AttributeArgs);
118-
let input = parse_macro_input!(input as ItemImpl);
119-
120-
match impl_::parser(args, input) {
121-
Ok(parsed) => parsed,
122-
Err(e) => syn::Error::new(Span::call_site(), e).to_compile_error(),
123-
}
124-
.into()
118+
// let args = parse_macro_input!(args as AttributeArgs);
119+
// let input = parse_macro_input!(input as ItemImpl);
120+
//
121+
// match impl_::parser(args, input) {
122+
// Ok(parsed) => parsed,
123+
// Err(e) => syn::Error::new(Span::call_site(), e).to_compile_error(),
124+
// }
125+
// .into()
126+
syn::Error::new(Span::call_site(), "php_impl is not supported")
127+
.to_compile_error()
128+
.into()
125129
}
126130

127131
#[proc_macro_attribute]

crates/macros/src/module.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@ pub fn parser(input: ItemMod) -> Result<TokenStream> {
5656
continue;
5757
}
5858
}
59+
Item::Impl(i) => {
60+
if i.attrs
61+
.iter()
62+
.find(|a| a.path.is_ident("php_impl"))
63+
.is_some()
64+
{
65+
builder.add_implementation(i.clone());
66+
continue;
67+
}
68+
}
5969
_ => {}
6070
}
6171
builder.add_unmapped(item.clone());

0 commit comments

Comments
 (0)