Skip to content

Commit 7a9a197

Browse files
committed
Support marking classes as interfaces
This allows passing flags as part of `#[php_class(flags=Interface]` etc, which allows one to mark a class as being an interface. When a class is an interface, it also shouldn't get a constructor created for it.
1 parent 8f1cfec commit 7a9a197

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

crates/macros/src/class.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub struct Class {
2222
/// A function name called when creating the class entry. Given an instance
2323
/// of `ClassBuilder` and must return it.
2424
pub modifier: Option<String>,
25+
pub flags: Option<String>
2526
}
2627

2728
#[derive(Debug)]
@@ -37,6 +38,7 @@ pub enum ParsedAttribute {
3738
pub struct AttrArgs {
3839
name: Option<String>,
3940
modifier: Option<String>,
41+
flags: Option<Expr>,
4042
}
4143

4244
pub fn parser(args: AttributeArgs, mut input: ItemStruct) -> Result<TokenStream> {
@@ -117,6 +119,7 @@ pub fn parser(args: AttributeArgs, mut input: ItemStruct) -> Result<TokenStream>
117119
let ItemStruct { ident, .. } = &input;
118120
let class_name = args.name.unwrap_or_else(|| ident.to_string());
119121
let struct_path = ident.to_string();
122+
let flags = args.flags.map(|flags|flags.to_token_stream().to_string());
120123
let class = Class {
121124
class_name,
122125
struct_path,
@@ -125,6 +128,7 @@ pub fn parser(args: AttributeArgs, mut input: ItemStruct) -> Result<TokenStream>
125128
docs: comments,
126129
properties,
127130
modifier: args.modifier,
131+
flags,
128132
..Default::default()
129133
};
130134

crates/macros/src/startup_function.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,14 +121,41 @@ fn build_classes(classes: &HashMap<String, Class>) -> Result<Vec<TokenStream>> {
121121
}
122122
});
123123

124+
let flags = {
125+
if let Some(flags) = &class.flags {
126+
let mut name = "::ext_php_rs::flags::ClassFlags::".to_owned();
127+
name.push_str(flags);
128+
let expr: Expr = syn::parse_str(&name).map_err(|_| {
129+
anyhow!("Invalid expression given for `{}` flags", class_name)
130+
})?;
131+
Some(quote! { .flags(#expr) })
132+
} else {
133+
None
134+
}
135+
};
136+
137+
let object_override = {
138+
if let Some(flags) = &class.flags {
139+
if flags == "Interface" {
140+
None
141+
} else {
142+
Some(quote! { .object_override::<#ident>() })
143+
}
144+
} else {
145+
Some(quote! { .object_override::<#ident>() })
146+
}
147+
};
148+
124149
Ok(quote! {{
125150
let builder = ::ext_php_rs::builders::ClassBuilder::new(#class_name)
126151
#(#methods)*
127152
#(#constants)*
128153
#(#interfaces)*
129154
// #(#properties)*
130155
#parent
131-
.object_override::<#ident>();
156+
#flags
157+
#object_override
158+
;
132159
#class_modifier
133160
let class = builder.build()
134161
.expect(concat!("Unable to build class `", #class_name, "`"));

0 commit comments

Comments
 (0)