@@ -8,11 +8,11 @@ use crate::{
88} ;
99use proc_macro2:: { Ident , Span , TokenStream } ;
1010use quote:: quote;
11- use syn:: { punctuated:: Punctuated , FnArg , ImplItemMethod , Lit , Pat , Signature , Token , Type } ;
11+ use syn:: { punctuated:: Punctuated , FnArg , ImplItemMethod , Lit , Pat , Token , Type } ;
1212
1313#[ derive( Debug , Clone ) ]
1414pub enum Arg {
15- Receiver ( bool ) ,
15+ Receiver ( MethodType ) ,
1616 Typed ( function:: Arg ) ,
1717}
1818
@@ -45,6 +45,13 @@ pub struct ParsedMethod {
4545 pub constructor : bool ,
4646}
4747
48+ #[ derive( Debug , Clone , Copy ) ]
49+ pub enum MethodType {
50+ Receiver { mutable : bool } ,
51+ ReceiverClassObject ,
52+ Static ,
53+ }
54+
4855impl ParsedMethod {
4956 pub fn new (
5057 tokens : TokenStream ,
@@ -61,7 +68,7 @@ impl ParsedMethod {
6168 }
6269}
6370
64- pub fn parser ( input : & mut ImplItemMethod , rename_rule : RenameRule ) -> Result < ParsedMethod > {
71+ pub fn parser ( mut input : ImplItemMethod , rename_rule : RenameRule ) -> Result < ParsedMethod > {
6572 let mut defaults = HashMap :: new ( ) ;
6673 let mut optional = None ;
6774 let mut visibility = Visibility :: Public ;
@@ -94,19 +101,13 @@ pub fn parser(input: &mut ImplItemMethod, rename_rule: RenameRule) -> Result<Par
94101 as_prop = Some ( ( prop_name, ty) )
95102 }
96103 ParsedAttribute :: Constructor => is_constructor = true ,
104+ _ => bail ! ( "Invalid attribute for method." ) ,
97105 }
98106 }
99107
100108 input. attrs . clear ( ) ;
101109
102- let ImplItemMethod { sig, .. } = & input;
103- let Signature {
104- ident,
105- output,
106- inputs,
107- ..
108- } = & sig;
109-
110+ let ident = & input. sig . ident ;
110111 let name = identifier. unwrap_or_else ( || rename_rule. rename ( ident. to_string ( ) ) ) ;
111112 if name == "__construct" {
112113 is_constructor = true ;
@@ -122,31 +123,25 @@ pub fn parser(input: &mut ImplItemMethod, rename_rule: RenameRule) -> Result<Par
122123 quote ! { return ; }
123124 } ;
124125 let internal_ident = Ident :: new ( & format ! ( "_internal_php_{}" , ident) , Span :: call_site ( ) ) ;
125- let args = build_args ( inputs, & defaults) ?;
126+ let args = build_args ( & mut input . sig . inputs , & defaults) ?;
126127 let optional = function:: find_optional_parameter (
127128 args. iter ( ) . filter_map ( |arg| match arg {
128129 Arg :: Typed ( arg) => Some ( arg) ,
129130 _ => None ,
130131 } ) ,
131132 optional,
132133 ) ;
133- let ( arg_definitions, is_static ) = build_arg_definitions ( & args) ;
134+ let ( arg_definitions, method_type ) = build_arg_definitions ( & args) ;
134135 let arg_parser = build_arg_parser (
135136 args. iter ( ) ,
136137 & optional,
137138 & bail,
138- if is_static {
139- ParserType :: StaticMethod
140- } else {
141- ParserType :: Method
139+ match method_type {
140+ MethodType :: Static => ParserType :: StaticMethod ,
141+ _ => ParserType :: Method ,
142142 } ,
143143 ) ?;
144144 let arg_accessors = build_arg_accessors ( & args, & bail) ;
145- let this = if is_static {
146- quote ! { Self :: }
147- } else {
148- quote ! { this. }
149- } ;
150145
151146 let func = if is_constructor {
152147 quote ! {
@@ -166,6 +161,11 @@ pub fn parser(input: &mut ImplItemMethod, rename_rule: RenameRule) -> Result<Par
166161 }
167162 }
168163 } else {
164+ let this = match method_type {
165+ MethodType :: Receiver { .. } => quote ! { this. } ,
166+ MethodType :: ReceiverClassObject | MethodType :: Static => quote ! { Self :: } ,
167+ } ;
168+
169169 quote ! {
170170 #input
171171
@@ -179,7 +179,7 @@ pub fn parser(input: &mut ImplItemMethod, rename_rule: RenameRule) -> Result<Par
179179 #( #arg_definitions) *
180180 #arg_parser
181181
182- let result = #this #ident( #( #arg_accessors, ) * ) ;
182+ let result = #this #ident( #( #arg_accessors, ) * ) ;
183183
184184 if let Err ( e) = result. set_zval( retval, false ) {
185185 let e: :: ext_php_rs:: exception:: PhpException = e. into( ) ;
@@ -195,51 +195,65 @@ pub fn parser(input: &mut ImplItemMethod, rename_rule: RenameRule) -> Result<Par
195195 orig_ident : ident. to_string ( ) ,
196196 args,
197197 optional,
198- output : crate :: function:: get_return_type ( output) ?,
199- _static : is_static ,
198+ output : crate :: function:: get_return_type ( & input . sig . output ) ?,
199+ _static : matches ! ( method_type , MethodType :: Static ) ,
200200 visibility,
201201 } ;
202202
203203 Ok ( ParsedMethod :: new ( func, method, as_prop, is_constructor) )
204204}
205205
206206fn build_args (
207- inputs : & Punctuated < FnArg , Token ! [ , ] > ,
207+ inputs : & mut Punctuated < FnArg , Token ! [ , ] > ,
208208 defaults : & HashMap < String , Lit > ,
209209) -> Result < Vec < Arg > > {
210210 inputs
211- . iter ( )
211+ . iter_mut ( )
212212 . map ( |arg| match arg {
213213 FnArg :: Receiver ( receiver) => {
214214 if receiver. reference . is_none ( ) {
215215 bail ! ( "`self` parameter must be a reference." ) ;
216216 }
217- Ok ( Arg :: Receiver ( receiver. mutability . is_some ( ) ) )
217+ Ok ( Arg :: Receiver ( MethodType :: Receiver {
218+ mutable : receiver. mutability . is_some ( ) ,
219+ } ) )
218220 }
219221 FnArg :: Typed ( ty) => {
220- let name = match & * ty. pat {
221- Pat :: Ident ( pat) => pat. ident . to_string ( ) ,
222- _ => bail ! ( "Invalid parameter type." ) ,
223- } ;
224- let default = defaults. get ( & name) ;
225- Ok ( Arg :: Typed (
226- crate :: function:: Arg :: from_type ( name. clone ( ) , & ty. ty , default, false )
227- . ok_or_else ( || anyhow ! ( "Invalid parameter type for `{}`." , name) ) ?,
228- ) )
222+ let mut this = false ;
223+ let attrs = std:: mem:: take ( & mut ty. attrs ) ;
224+ for attr in attrs. into_iter ( ) {
225+ match parse_attribute ( & attr) ? {
226+ ParsedAttribute :: This => this = true ,
227+ _ => bail ! ( "Invalid attribute for argument." ) ,
228+ }
229+ }
230+
231+ if this {
232+ Ok ( Arg :: Receiver ( MethodType :: ReceiverClassObject ) )
233+ } else {
234+ let name = match & * ty. pat {
235+ Pat :: Ident ( pat) => pat. ident . to_string ( ) ,
236+ _ => bail ! ( "Invalid parameter type." ) ,
237+ } ;
238+ let default = defaults. get ( & name) ;
239+ Ok ( Arg :: Typed (
240+ crate :: function:: Arg :: from_type ( name. clone ( ) , & ty. ty , default, false )
241+ . ok_or_else ( || anyhow ! ( "Invalid parameter type for `{}`." , name) ) ?,
242+ ) )
243+ }
229244 }
230245 } )
231246 . collect ( )
232247}
233248
234- fn build_arg_definitions ( args : & [ Arg ] ) -> ( Vec < TokenStream > , bool ) {
235- let mut _static = true ;
249+ fn build_arg_definitions ( args : & [ Arg ] ) -> ( Vec < TokenStream > , MethodType ) {
250+ let mut method_type = MethodType :: Static ;
236251
237252 (
238253 args. iter ( )
239254 . filter_map ( |ty| match ty {
240- Arg :: Receiver ( _) => {
241- _static = false ;
242-
255+ Arg :: Receiver ( t) => {
256+ method_type = * t;
243257 None
244258 }
245259 Arg :: Typed ( arg) => {
@@ -251,7 +265,7 @@ fn build_arg_definitions(args: &[Arg]) -> (Vec<TokenStream>, bool) {
251265 }
252266 } )
253267 . collect ( ) ,
254- _static ,
268+ method_type ,
255269 )
256270}
257271
@@ -276,6 +290,7 @@ fn build_arg_accessors(args: &[Arg], ret: &TokenStream) -> Vec<TokenStream> {
276290 args. iter ( )
277291 . filter_map ( |arg| match arg {
278292 Arg :: Typed ( arg) => Some ( arg. get_accessor ( ret) ) ,
293+ Arg :: Receiver ( MethodType :: ReceiverClassObject ) => Some ( quote ! { this } ) ,
279294 _ => None ,
280295 } )
281296 . collect ( )
0 commit comments