Skip to content

Commit 3d26586

Browse files
committed
chore: More php_interface proc attribute macro
chore: Add pub in impl_
1 parent b33d707 commit 3d26586

File tree

3 files changed

+102
-18
lines changed

3 files changed

+102
-18
lines changed

crates/macros/src/impl_.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,15 @@ impl RenameRule {
6262

6363
/// Method visibilities.
6464
#[derive(Debug)]
65-
enum MethodVis {
65+
pub enum MethodVis {
6666
Public,
6767
Private,
6868
Protected,
6969
}
7070

7171
/// Method types.
7272
#[derive(Debug)]
73-
enum MethodTy {
73+
pub enum MethodTy {
7474
/// Regular PHP method.
7575
Normal,
7676
/// Constructor method.
@@ -122,21 +122,21 @@ pub fn parser(args: TokenStream, mut input: ItemImpl) -> Result<TokenStream> {
122122

123123
/// Arguments applied to methods.
124124
#[derive(Debug)]
125-
struct MethodArgs {
125+
pub struct MethodArgs {
126126
/// Method name. Only applies to PHP (not the Rust method name).
127-
name: String,
127+
pub name: String,
128128
/// The first optional argument of the function signature.
129-
optional: Option<Ident>,
129+
pub optional: Option<Ident>,
130130
/// Default values for optional arguments.
131-
defaults: HashMap<Ident, Lit>,
131+
pub defaults: HashMap<Ident, Lit>,
132132
/// Visibility of the method (public, protected, private).
133-
vis: MethodVis,
133+
pub vis: MethodVis,
134134
/// Method type.
135-
ty: MethodTy,
135+
pub ty: MethodTy,
136136
}
137137

138138
impl MethodArgs {
139-
fn new(name: String) -> Self {
139+
pub fn new(name: String) -> Self {
140140
let ty = if name == "__construct" {
141141
MethodTy::Constructor
142142
} else {
@@ -151,7 +151,7 @@ impl MethodArgs {
151151
}
152152
}
153153

154-
fn parse(&mut self, attrs: &mut Vec<syn::Attribute>) -> Result<()> {
154+
pub fn parse(&mut self, attrs: &mut Vec<syn::Attribute>) -> Result<()> {
155155
let mut unparsed = vec![];
156156
unparsed.append(attrs);
157157
for attr in unparsed {
@@ -216,7 +216,7 @@ struct ParsedImpl<'a> {
216216
}
217217

218218
#[derive(Debug)]
219-
struct FnBuilder {
219+
pub struct FnBuilder {
220220
/// Tokens which represent the FunctionBuilder for this function.
221221
pub builder: TokenStream,
222222
/// The visibility of this method.
@@ -226,7 +226,7 @@ struct FnBuilder {
226226
}
227227

228228
#[derive(Debug)]
229-
struct Constant<'a> {
229+
pub struct Constant<'a> {
230230
/// Name of the constant in PHP land.
231231
name: String,
232232
/// Identifier of the constant in Rust land.

crates/macros/src/interface.rs

Lines changed: 88 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,92 @@
1-
use crate::prelude::*;
1+
use std::collections::HashMap;
2+
3+
use crate::{
4+
function::{Args, CallType, Function, MethodReceiver},
5+
helpers::get_docs,
6+
impl_::{Constant, FnBuilder, MethodArgs, MethodTy},
7+
prelude::*,
8+
};
9+
use darling::{ast::NestedMeta, FromMeta, ToTokens};
210
use proc_macro2::TokenStream;
311
use quote::quote;
4-
use syn::TraitItem;
12+
use syn::{Ident, ItemTrait, Lit, TraitItem, TraitItemFn};
13+
14+
#[derive(Debug, Default, FromMeta)]
15+
#[darling(default)]
16+
pub struct StructArgs {
17+
/// The name of the PHP interface. Defaults to the same name as the trait.
18+
name: Option<String>,
19+
}
20+
21+
#[derive(Debug)]
22+
struct ParsedTrait<'a> {
23+
path: &'a syn::Path,
24+
constructor: Option<Function<'a>>,
25+
functions: Vec<FnBuilder>,
26+
constants: Vec<Constant<'a>>,
27+
}
28+
29+
impl<'a> ParsedTrait<'a> {
30+
fn parse(&mut self, items: impl Iterator<Item = &'a mut syn::TraitItem>) -> Result<()> {
31+
for item in items {
32+
match item {
33+
syn::TraitItem::Fn(method) => {
34+
let name = method.sig.ident.to_string();
35+
let docs = get_docs(&method.attrs);
36+
let mut opts = MethodArgs::new(name);
37+
opts.parse(&mut method.attrs)?;
38+
let args = Args::parse_from_fnargs(method.sig.inputs.iter(), opts.defaults)?;
39+
let mut func =
40+
Function::new(&method.sig, Some(opts.name), args, opts.optional, docs)?;
41+
42+
if matches!(opts.ty, MethodTy::Constructor) {
43+
if self.constructor.replace(func).is_some() {
44+
bail!(method => "Only one constructor can be provided per class.");
45+
}
46+
} else {
47+
let call_type = CallType::Method {
48+
class: self.path,
49+
receiver: if func.args.receiver.is_some() {
50+
// `&self` or `&mut self`
51+
MethodReceiver::Class
52+
} else if func
53+
.args
54+
.typed
55+
.first()
56+
.map(|arg| arg.name == "self_")
57+
.unwrap_or_default()
58+
{
59+
// `self_: &[mut] ZendClassObject<Self>`
60+
// Need to remove arg from argument list
61+
func.args.typed.pop();
62+
MethodReceiver::ZendClassObject
63+
} else {
64+
// Static method
65+
MethodReceiver::Static
66+
},
67+
};
68+
let builder = func.function_builder(call_type)?;
69+
self.functions.push(FnBuilder {
70+
builder,
71+
vis: opts.vis,
72+
r#abstract: false,
73+
});
74+
}
75+
}
76+
_ => {}
77+
}
78+
}
79+
Ok(())
80+
}
81+
}
82+
83+
pub fn parser(args: TokenStream, input: ItemTrait) -> Result<TokenStream> {
84+
let meta = NestedMeta::parse_meta_list(args)?;
85+
86+
let args = match StructArgs::from_list(&meta) {
87+
Ok(args) => args,
88+
Err(e) => bail!("Failed to parse struct arguments: {:?}", e),
89+
};
590

6-
pub fn parser(args: TokenStream, input: TraitItem) -> Result<TokenStream> {
7-
Ok(quote! {()})
91+
Ok(quote! {})
892
}

crates/macros/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ mod zval;
1414
use proc_macro::TokenStream;
1515
use syn::{
1616
parse_macro_input, DeriveInput, ItemConst, ItemFn, ItemForeignMod, ItemImpl, ItemStruct,
17-
TraitItem,
17+
ItemTrait, TraitItem,
1818
};
1919

2020
extern crate proc_macro;
@@ -213,7 +213,7 @@ pub fn php_class(args: TokenStream, input: TokenStream) -> TokenStream {
213213
/// ```
214214
#[proc_macro_attribute]
215215
pub fn php_interface(args: TokenStream, input: TokenStream) -> TokenStream {
216-
let input = parse_macro_input!(input as TraitItem);
216+
let input = parse_macro_input!(input as ItemTrait);
217217

218218
interface::parser(args.into(), input)
219219
.unwrap_or_else(|e| e.to_compile_error())

0 commit comments

Comments
 (0)