From a57187d0dff93ce63cccd4d160f6ee40d3119da6 Mon Sep 17 00:00:00 2001 From: Alessandro Chitolina Date: Sat, 24 May 2025 00:11:29 +0200 Subject: [PATCH] feat: argument defaults can be any expr valid in const scope (None for example) --- crates/macros/src/function.rs | 9 +++---- crates/macros/src/impl_.rs | 6 ++--- tests/src/integration/defaults/defaults.php | 6 +++++ tests/src/integration/defaults/mod.rs | 27 +++++++++++++++++++++ tests/src/integration/mod.rs | 1 + tests/src/lib.rs | 1 + 6 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 tests/src/integration/defaults/defaults.php create mode 100644 tests/src/integration/defaults/mod.rs diff --git a/crates/macros/src/function.rs b/crates/macros/src/function.rs index d84363d9bf..c05c3767a8 100644 --- a/crates/macros/src/function.rs +++ b/crates/macros/src/function.rs @@ -4,8 +4,7 @@ use darling::{FromAttributes, ToTokens}; use proc_macro2::{Ident, Span, TokenStream}; use quote::{format_ident, quote}; use syn::spanned::Spanned as _; -use syn::PatType; -use syn::{FnArg, GenericArgument, ItemFn, Lit, PathArguments, Type, TypePath}; +use syn::{Expr, FnArg, GenericArgument, ItemFn, PatType, PathArguments, Type, TypePath}; use crate::helpers::get_docs; use crate::parsing::{PhpRename, Visibility}; @@ -28,7 +27,7 @@ pub fn wrap(input: &syn::Path) -> Result { struct PhpFunctionAttribute { #[darling(flatten)] rename: PhpRename, - defaults: HashMap, + defaults: HashMap, optional: Option, vis: Option, attrs: Vec, @@ -381,7 +380,7 @@ pub struct TypedArg<'a> { pub name: &'a Ident, pub ty: Type, pub nullable: bool, - pub default: Option, + pub default: Option, pub as_ref: bool, pub variadic: bool, } @@ -395,7 +394,7 @@ pub struct Args<'a> { impl<'a> Args<'a> { pub fn parse_from_fnargs( args: impl Iterator, - mut defaults: HashMap, + mut defaults: HashMap, ) -> Result { let mut result = Self { receiver: None, diff --git a/crates/macros/src/impl_.rs b/crates/macros/src/impl_.rs index 2de298da22..ac0e6a8d7e 100644 --- a/crates/macros/src/impl_.rs +++ b/crates/macros/src/impl_.rs @@ -3,7 +3,7 @@ use darling::FromAttributes; use proc_macro2::TokenStream; use quote::quote; use std::collections::{HashMap, HashSet}; -use syn::{Ident, ItemImpl, Lit}; +use syn::{Expr, Ident, ItemImpl}; use crate::constant::PhpConstAttribute; use crate::function::{Args, CallType, Function, MethodReceiver}; @@ -68,7 +68,7 @@ struct MethodArgs { /// The first optional argument of the function signature. optional: Option, /// Default values for optional arguments. - defaults: HashMap, + defaults: HashMap, /// Visibility of the method (public, protected, private). vis: Visibility, /// Method type. @@ -80,7 +80,7 @@ struct MethodArgs { pub struct PhpFunctionImplAttribute { #[darling(flatten)] rename: PhpRename, - defaults: HashMap, + defaults: HashMap, optional: Option, vis: Option, attrs: Vec, diff --git a/tests/src/integration/defaults/defaults.php b/tests/src/integration/defaults/defaults.php new file mode 100644 index 0000000000..13e050c249 --- /dev/null +++ b/tests/src/integration/defaults/defaults.php @@ -0,0 +1,6 @@ + i32 { + a +} + +#[php_function] +#[php(defaults(a = None))] +pub fn test_defaults_nullable_string(a: Option) -> Option { + a +} + +pub fn build_module(builder: ModuleBuilder) -> ModuleBuilder { + builder + .function(wrap_function!(test_defaults_integer)) + .function(wrap_function!(test_defaults_nullable_string)) +} + +#[cfg(test)] +mod tests { + #[test] + fn defaults_works() { + assert!(crate::integration::test::run_php("defaults/defaults.php")); + } +} diff --git a/tests/src/integration/mod.rs b/tests/src/integration/mod.rs index bd16cc75c3..37798d0614 100644 --- a/tests/src/integration/mod.rs +++ b/tests/src/integration/mod.rs @@ -4,6 +4,7 @@ pub mod bool; pub mod callable; pub mod class; pub mod closure; +pub mod defaults; pub mod globals; pub mod iterator; pub mod magic_method; diff --git a/tests/src/lib.rs b/tests/src/lib.rs index f9a2f92ac3..1e0ff180a2 100644 --- a/tests/src/lib.rs +++ b/tests/src/lib.rs @@ -17,6 +17,7 @@ pub fn build_module(module: ModuleBuilder) -> ModuleBuilder { module = integration::callable::build_module(module); module = integration::class::build_module(module); module = integration::closure::build_module(module); + module = integration::defaults::build_module(module); module = integration::globals::build_module(module); module = integration::iterator::build_module(module); module = integration::magic_method::build_module(module);