Skip to content

Commit bc54a33

Browse files
committed
style(macro): cleanup from outer macro refactor
Refs: 335
1 parent 87f5c32 commit bc54a33

File tree

6 files changed

+96
-142
lines changed

6 files changed

+96
-142
lines changed

crates/macros/src/constant.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::helpers::get_docs;
2-
use anyhow::{bail, Result};
2+
use anyhow::Result;
33
use darling::ToTokens;
44
use proc_macro2::TokenStream;
55
use quote::quote;

crates/macros/src/function.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use darling::{FromMeta, ToTokens};
77
use proc_macro2::{Ident, Literal, Span, TokenStream};
88
use quote::quote;
99
use syn::{
10-
punctuated::Punctuated, AttributeArgs, FnArg, GenericArgument, ItemFn, Lit, PathArguments,
11-
ReturnType, Signature, Token, Type, TypePath,
10+
punctuated::Punctuated, FnArg, GenericArgument, ItemFn, Lit, PathArguments, ReturnType,
11+
Signature, Token, Type, TypePath,
1212
};
1313

1414
#[derive(Default, Debug, FromMeta)]

crates/macros/src/lib.rs

Lines changed: 60 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -13,78 +13,37 @@ mod startup_function;
1313
mod syn_ext;
1414
mod zval;
1515

16-
use std::collections::HashMap;
17-
18-
use constant::Constant;
19-
use darling::FromMeta;
2016
use proc_macro::TokenStream;
21-
use proc_macro2::{Span, TokenStream as TokenStream2};
22-
use syn::{
23-
parse_macro_input, AttributeArgs, DeriveInput, ItemConst, ItemFn, ItemForeignMod, ItemMod,
24-
NestedMeta,
25-
};
17+
use proc_macro2::Span;
18+
use syn::{parse_macro_input, DeriveInput, ItemFn, ItemForeignMod, ItemMod};
2619

2720
extern crate proc_macro;
2821

29-
#[derive(Default, Debug)]
30-
struct State {
31-
functions: Vec<function::Function>,
32-
classes: HashMap<String, class::Class>,
33-
constants: Vec<Constant>,
34-
}
35-
36-
impl State {
37-
fn parse_from_meta<T>(
38-
meta: &Vec<NestedMeta>,
39-
call_site: Option<Span>,
40-
) -> Result<T, TokenStream2>
41-
where
42-
T: FromMeta,
43-
{
44-
T::from_list(&meta).map_err(|e| {
45-
syn::Error::new(
46-
call_site.unwrap_or_else(Span::call_site),
47-
format!("Unable to parse attribute arguments: {:?}", e),
48-
)
49-
.to_compile_error()
50-
.into()
51-
})
52-
}
53-
}
54-
22+
/// Structs can be exported to PHP as classes with the #[php_class] attribute macro. This attribute derives the RegisteredClass trait on your struct, as well as registering the class to be registered with the #[php_module] macro.
5523
#[proc_macro_attribute]
5624
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()
25+
syn::Error::new(
26+
Span::call_site(),
27+
"php_class can only be used inside a #[php_module] module",
28+
)
29+
.to_compile_error()
30+
.into()
6831
}
6932

33+
/// Used to annotate functions which should be exported to PHP. Note that this should not be used on class methods - see the #[php_impl] macro for that.
7034
#[proc_macro_attribute]
71-
pub fn php_function(args: TokenStream, input: TokenStream) -> TokenStream {
72-
let args = parse_macro_input!(args as AttributeArgs);
73-
let input = parse_macro_input!(input as ItemFn);
74-
let attr_args = match State::parse_from_meta(&args, None) {
75-
Ok(attr_args) => attr_args,
76-
Err(e) => return e.into(),
77-
};
78-
79-
match function::parser(attr_args, &input) {
80-
Ok((parsed, _)) => parsed,
81-
Err(e) => syn::Error::new(Span::call_site(), e).to_compile_error(),
82-
}
35+
pub fn php_function(_args: TokenStream, _input: TokenStream) -> TokenStream {
36+
syn::Error::new(
37+
Span::call_site(),
38+
"php_function can only be used inside a #[php_module] module",
39+
)
40+
.to_compile_error()
8341
.into()
8442
}
8543

44+
/// The module macro is used to annotate the get_module function, which is used by the PHP interpreter to retrieve information about your extension, including the name, version, functions and extra initialization functions. Regardless if you use this macro, your extension requires a extern "C" fn get_module() so that PHP can get this information.
8645
#[proc_macro_attribute]
87-
pub fn php_module(_: TokenStream, input: TokenStream) -> TokenStream {
46+
pub fn php_module(_args: TokenStream, input: TokenStream) -> TokenStream {
8847
let input = parse_macro_input!(input as ItemMod);
8948

9049
match module::parser(input) {
@@ -94,51 +53,47 @@ pub fn php_module(_: TokenStream, input: TokenStream) -> TokenStream {
9453
.into()
9554
}
9655

56+
/// Used to define the PHP extension startup function. This function is used to register extension classes and constants with the PHP interpreter.
9757
#[proc_macro_attribute]
98-
pub fn php_startup(args: TokenStream, input: TokenStream) -> TokenStream {
99-
// let args = parse_macro_input!(args as AttributeArgs);
100-
// let input = parse_macro_input!(input as ItemFn);
101-
// let attr_args = match State::parse_from_meta(&args, None) {
102-
// Ok(attr_args) => attr_args,
103-
// Err(e) => return e.into(),
104-
// };
105-
//
106-
// match startup_function::parser(Some(attr_args), &input) {
107-
// Ok((parsed, _)) => parsed,
108-
// Err(e) => syn::Error::new(Span::call_site(), e).to_compile_error(),
109-
// }
110-
// .into()
111-
syn::Error::new(Span::call_site(), "php_startup is not supported")
112-
.to_compile_error()
113-
.into()
58+
pub fn php_startup(_args: TokenStream, _input: TokenStream) -> TokenStream {
59+
syn::Error::new(
60+
Span::call_site(),
61+
"php_startup can only be used inside a #[php_module] module",
62+
)
63+
.to_compile_error()
64+
.into()
11465
}
11566

67+
/// You can export an entire impl block to PHP. This exports all methods as well as constants to PHP on the class that it is implemented on. This requires the #[php_class] macro to already be used on the underlying struct. Trait implementations cannot be exported to PHP.
11668
#[proc_macro_attribute]
117-
pub fn php_impl(args: TokenStream, input: TokenStream) -> TokenStream {
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()
69+
pub fn php_impl(_args: TokenStream, _input: TokenStream) -> TokenStream {
70+
syn::Error::new(
71+
Span::call_site(),
72+
"php_impl can only be used inside a #[php_module] module",
73+
)
74+
.to_compile_error()
75+
.into()
12976
}
13077

78+
/// Exports a Rust constant as a global PHP constant. The constant can be any type that implements [`IntoConst`].
13179
#[proc_macro_attribute]
132-
pub fn php_const(_: TokenStream, input: TokenStream) -> TokenStream {
133-
let mut input = parse_macro_input!(input as ItemConst);
134-
135-
match constant::parser(&mut input) {
136-
Ok((parsed, _)) => parsed,
137-
Err(e) => syn::Error::new(Span::call_site(), e).to_compile_error(),
138-
}
80+
pub fn php_const(_args: TokenStream, _input: TokenStream) -> TokenStream {
81+
syn::Error::new(
82+
Span::call_site(),
83+
"php_const can only be used inside a #[php_module] module",
84+
)
85+
.to_compile_error()
13986
.into()
14087
}
14188

89+
/// Attribute used to annotate `extern` blocks which are deemed as PHP
90+
/// functions.
91+
///
92+
/// This allows you to 'import' PHP functions into Rust so that they can be
93+
/// called like regular Rust functions. Parameters can be any type that
94+
/// implements [`IntoZval`], and the return type can be anything that implements
95+
/// [`From<Zval>`] (notice how [`Zval`] is consumed rather than borrowed in this
96+
/// case).
14297
#[proc_macro_attribute]
14398
pub fn php_extern(_: TokenStream, input: TokenStream) -> TokenStream {
14499
let input = parse_macro_input!(input as ItemForeignMod);
@@ -150,6 +105,9 @@ pub fn php_extern(_: TokenStream, input: TokenStream) -> TokenStream {
150105
.into()
151106
}
152107

108+
/// Derives the traits required to convert a struct or enum to and from a
109+
/// [`Zval`]. Both [`FromZval`] and [`IntoZval`] are implemented on types which
110+
/// use this macro.
153111
#[proc_macro_derive(ZvalConvert)]
154112
pub fn zval_convert_derive(input: TokenStream) -> TokenStream {
155113
let input = parse_macro_input!(input as DeriveInput);
@@ -161,6 +119,14 @@ pub fn zval_convert_derive(input: TokenStream) -> TokenStream {
161119
.into()
162120
}
163121

122+
/// Defines an `extern` function with the Zend fastcall convention based on
123+
/// operating system.
124+
///
125+
/// On Windows, Zend fastcall functions use the vector calling convention, while
126+
/// on all other operating systems no fastcall convention is used (just the
127+
/// regular C calling convention).
128+
///
129+
/// This macro wraps a function and applies the correct calling convention.
164130
#[proc_macro]
165131
pub fn zend_fastcall(input: TokenStream) -> TokenStream {
166132
let input = parse_macro_input!(input as ItemFn);

crates/macros/src/module.rs

Lines changed: 17 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1+
use std::collections::HashMap;
2+
13
use anyhow::Result;
24
use proc_macro2::{Ident, Span, TokenStream};
35
use quote::quote;
46
use syn::{Item, ItemMod, Type};
57

68
use crate::{
79
class::{Class, Property},
10+
constant::Constant,
811
function::{Arg, Function},
912
module_builder::ModuleBuilder,
10-
State,
1113
};
1214

1315
pub fn parser(input: ItemMod) -> Result<TokenStream> {
@@ -25,19 +27,10 @@ pub fn parser(input: ItemMod) -> Result<TokenStream> {
2527
for item in content {
2628
match item {
2729
Item::Fn(f) => {
28-
if f.attrs
29-
.iter()
30-
.find(|a| a.path.is_ident("php_startup"))
31-
.is_some()
32-
{
30+
if f.attrs.iter().any(|a| a.path.is_ident("php_startup")) {
3331
builder.set_startup_function(f.clone());
3432
continue;
35-
} else if f
36-
.attrs
37-
.iter()
38-
.find(|a| a.path.is_ident("php_function"))
39-
.is_some()
40-
{
33+
} else if f.attrs.iter().any(|a| a.path.is_ident("php_function")) {
4134
builder.add_function(f.clone());
4235
continue;
4336
}
@@ -47,21 +40,13 @@ pub fn parser(input: ItemMod) -> Result<TokenStream> {
4740
continue;
4841
}
4942
Item::Struct(s) => {
50-
if s.attrs
51-
.iter()
52-
.find(|a| a.path.is_ident("php_class"))
53-
.is_some()
54-
{
43+
if s.attrs.iter().any(|a| a.path.is_ident("php_class")) {
5544
builder.add_class(s.clone());
5645
continue;
5746
}
5847
}
5948
Item::Impl(i) => {
60-
if i.attrs
61-
.iter()
62-
.find(|a| a.path.is_ident("php_impl"))
63-
.is_some()
64-
{
49+
if i.attrs.iter().any(|a| a.path.is_ident("php_impl")) {
6550
builder.add_implementation(i.clone());
6651
continue;
6752
}
@@ -142,8 +127,12 @@ pub trait Describe {
142127
fn describe(&self) -> TokenStream;
143128
}
144129

145-
fn generate_stubs(state: &State) -> TokenStream {
146-
let module = state.describe();
130+
pub(crate) fn generate_stubs(
131+
functions: &[Function],
132+
classes: &HashMap<String, Class>,
133+
constants: &[Constant],
134+
) -> TokenStream {
135+
let module = (functions, classes, constants).describe();
147136

148137
quote! {
149138
#[cfg(debug_assertions)]
@@ -354,11 +343,11 @@ impl Describe for crate::constant::Constant {
354343
}
355344
}
356345

357-
impl Describe for State {
346+
impl Describe for (&[Function], &HashMap<String, Class>, &[Constant]) {
358347
fn describe(&self) -> TokenStream {
359-
let functs = self.functions.iter().map(Describe::describe);
360-
let classes = self.classes.values().map(|class| class.describe());
361-
let constants = self.constants.iter().map(Describe::describe);
348+
let functs = self.0.iter().map(Describe::describe);
349+
let classes = self.1.values().map(|class| class.describe());
350+
let constants = self.2.iter().map(Describe::describe);
362351

363352
quote! {
364353
Module {

0 commit comments

Comments
 (0)