Skip to content

Commit 645ffb8

Browse files
authored
fix(macro): add missing static flags in php_impl macro
Refs: #419
1 parent 90dfe33 commit 645ffb8

File tree

3 files changed

+43
-5
lines changed

3 files changed

+43
-5
lines changed

crates/macros/src/impl_.rs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use darling::util::Flag;
22
use darling::FromAttributes;
33
use proc_macro2::TokenStream;
44
use quote::quote;
5-
use std::collections::HashMap;
5+
use std::collections::{HashMap, HashSet};
66
use syn::{Ident, ItemImpl, Lit};
77

88
use crate::constant::PhpConstAttribute;
@@ -124,14 +124,30 @@ struct ParsedImpl<'a> {
124124
constants: Vec<Constant<'a>>,
125125
}
126126

127+
#[derive(Debug, Eq, Hash, PartialEq)]
128+
enum MethodModifier {
129+
Abstract,
130+
Static,
131+
}
132+
133+
impl quote::ToTokens for MethodModifier {
134+
fn to_tokens(&self, tokens: &mut TokenStream) {
135+
match *self {
136+
Self::Abstract => quote! { ::ext_php_rs::flags::MethodFlags::Abstract },
137+
Self::Static => quote! { ::ext_php_rs::flags::MethodFlags::Static },
138+
}
139+
.to_tokens(tokens);
140+
}
141+
}
142+
127143
#[derive(Debug)]
128144
struct FnBuilder {
129145
/// Tokens which represent the `FunctionBuilder` for this function.
130146
pub builder: TokenStream,
131147
/// The visibility of this method.
132148
pub vis: Visibility,
133149
/// Whether this method is abstract.
134-
pub r#abstract: bool,
150+
pub modifiers: HashSet<MethodModifier>,
135151
}
136152

137153
#[derive(Debug)]
@@ -190,6 +206,8 @@ impl<'a> ParsedImpl<'a> {
190206
let args = Args::parse_from_fnargs(method.sig.inputs.iter(), opts.defaults)?;
191207
let mut func = Function::new(&method.sig, opts.name, args, opts.optional, docs);
192208

209+
let mut modifiers: HashSet<MethodModifier> = HashSet::new();
210+
193211
if matches!(opts.ty, MethodTy::Constructor) {
194212
if self.constructor.replace(func).is_some() {
195213
bail!(method => "Only one constructor can be provided per class.");
@@ -211,15 +229,21 @@ impl<'a> ParsedImpl<'a> {
211229
func.args.typed.pop();
212230
MethodReceiver::ZendClassObject
213231
} else {
232+
modifiers.insert(MethodModifier::Static);
214233
// Static method
215234
MethodReceiver::Static
216235
},
217236
};
237+
if matches!(opts.ty, MethodTy::Abstract) {
238+
modifiers.insert(MethodModifier::Abstract);
239+
}
240+
218241
let builder = func.function_builder(call_type);
242+
219243
self.functions.push(FnBuilder {
220244
builder,
221245
vis: opts.vis,
222-
r#abstract: matches!(opts.ty, MethodTy::Abstract),
246+
modifiers,
223247
});
224248
}
225249
}
@@ -284,9 +308,10 @@ impl quote::ToTokens for FnBuilder {
284308
Visibility::Protected => quote! { ::ext_php_rs::flags::MethodFlags::Protected },
285309
Visibility::Private => quote! { ::ext_php_rs::flags::MethodFlags::Private },
286310
});
287-
if self.r#abstract {
288-
flags.push(quote! { ::ext_php_rs::flags::MethodFlags::Abstract });
311+
for flag in &self.modifiers {
312+
flags.push(quote! { #flag })
289313
}
314+
290315
quote! {
291316
(#builder, #(#flags)|*)
292317
}

tests/src/integration/class.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,12 @@
1919
assert($class->boolean);
2020
$class->boolean = false;
2121
assert($class->boolean === false);
22+
23+
// Call regular from object
24+
assert($class->staticCall('Php') === 'Hello Php');
25+
26+
// Call static from object
27+
assert($class::staticCall('Php') === 'Hello Php');
28+
29+
// Call static from class
30+
assert(TestClass::staticCall('Php') === 'Hello Php');

tests/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,10 @@ impl TestClass {
210210
pub fn set_number(&mut self, number: i32) {
211211
self.number = number;
212212
}
213+
214+
pub fn static_call(name: String) -> String {
215+
format!("Hello {name}")
216+
}
213217
}
214218

215219
#[php_function]

0 commit comments

Comments
 (0)