From 1b1866f241076be5b15390bb3e7905cbff04ebce Mon Sep 17 00:00:00 2001 From: Xenira <1288524+Xenira@users.noreply.github.com> Date: Mon, 23 Jun 2025 23:25:16 +0200 Subject: [PATCH 1/2] refactor(macro): change `rename` to `change_case` `name` and `rename` were too similar, so `rename` has been changed to `change_case`. Also added a script to update the documentation of the macro crate. Refs: #466 --- crates/macros/src/impl_.rs | 24 +++++++------ crates/macros/src/lib.rs | 55 +++++++++++++++++++---------- crates/macros/src/parsing.rs | 33 ++++++++--------- guide/src/macros/classes.md | 8 ++--- guide/src/macros/constant.md | 4 +-- guide/src/macros/impl.md | 16 ++++----- guide/src/macros/php.md | 44 +++++++++++------------ guide/src/migration-guides/v0.14.md | 24 ++++++------- tools/update_lib_docs.sh | 55 +++++++++++++++++++++++++++++ 9 files changed, 170 insertions(+), 93 deletions(-) create mode 100755 tools/update_lib_docs.sh diff --git a/crates/macros/src/impl_.rs b/crates/macros/src/impl_.rs index 585ec51c8b..7c931dcc75 100644 --- a/crates/macros/src/impl_.rs +++ b/crates/macros/src/impl_.rs @@ -30,9 +30,9 @@ enum MethodTy { #[darling(attributes(php), default)] pub struct PhpImpl { /// Rename methods to match the given rule. - rename_methods: Option, + change_method_case: Option, /// Rename constants to match the given rule. - rename_constants: Option, + change_constant_case: Option, } pub fn parser(mut input: ItemImpl) -> Result { @@ -47,8 +47,9 @@ pub fn parser(mut input: ItemImpl) -> Result { let mut parsed = ParsedImpl::new( path, - args.rename_methods.unwrap_or(RenameRule::Camel), - args.rename_constants.unwrap_or(RenameRule::ScreamingSnake), + args.change_method_case.unwrap_or(RenameRule::Camel), + args.change_constant_case + .unwrap_or(RenameRule::ScreamingSnake), ); parsed.parse(input.items.iter_mut())?; @@ -116,8 +117,8 @@ impl MethodArgs { #[derive(Debug)] struct ParsedImpl<'a> { path: &'a syn::Path, - rename_methods: RenameRule, - rename_constants: RenameRule, + change_method_case: RenameRule, + change_constant_case: RenameRule, functions: Vec, constructor: Option>, constants: Vec>, @@ -165,12 +166,13 @@ impl<'a> ParsedImpl<'a> { /// # Parameters /// /// * `path` - Path of the type the `impl` block is for. - /// * `rename` - Rename rule for methods. + /// * `rename_methods` - Rule to rename methods with. + /// * `rename_constants` - Rule to rename constants with. fn new(path: &'a syn::Path, rename_methods: RenameRule, rename_constants: RenameRule) -> Self { Self { path, - rename_methods, - rename_constants, + change_method_case: rename_methods, + change_constant_case: rename_constants, functions: Vec::default(), constructor: Option::default(), constants: Vec::default(), @@ -185,7 +187,7 @@ impl<'a> ParsedImpl<'a> { let attr = PhpConstAttribute::from_attributes(&c.attrs)?; let name = attr .rename - .rename(c.ident.to_string(), self.rename_constants); + .rename(c.ident.to_string(), self.change_constant_case); let docs = get_docs(&attr.attrs)?; c.attrs.retain(|attr| !attr.path().is_ident("php")); @@ -199,7 +201,7 @@ impl<'a> ParsedImpl<'a> { let attr = PhpFunctionImplAttribute::from_attributes(&method.attrs)?; let name = attr .rename - .rename_method(method.sig.ident.to_string(), self.rename_methods); + .rename_method(method.sig.ident.to_string(), self.change_method_case); let docs = get_docs(&attr.attrs)?; method.attrs.retain(|attr| !attr.path().is_ident("php")); diff --git a/crates/macros/src/lib.rs b/crates/macros/src/lib.rs index 4ddb2f6521..8c2c1a398b 100644 --- a/crates/macros/src/lib.rs +++ b/crates/macros/src/lib.rs @@ -18,6 +18,7 @@ use syn::{ extern crate proc_macro; +// BEGIN DOCS FROM classes.md /// # `#[php_class]` Attribute /// /// Structs can be exported to PHP as classes with the `#[php_class]` attribute @@ -33,7 +34,7 @@ extern crate proc_macro; /// - `name` - Changes the name of the class when exported to PHP. The Rust /// struct name is kept the same. If no name is given, the name of the struct /// is used. Useful for namespacing classes. -/// - `rename` - Changes the case of the class name when exported to PHP. +/// - `change_case` - Changes the case of the class name when exported to PHP. /// - `#[php(extends(ce = ce_fn, stub = "ParentClass"))]` - Sets the parent /// class of the class. Can only be used once. `ce_fn` must be a function with /// the signature `fn() -> &'static ClassEntry`. @@ -50,8 +51,8 @@ extern crate proc_macro; /// /// - `name` - Allows you to rename the property, e.g. `#[php(name = /// "new_name")]` -/// - `rename` - Allows you to rename the property using rename rules, e.g. -/// `#[php(rename = PascalCase)]` +/// - `change_case` - Allows you to rename the property using rename rules, e.g. +/// `#[php(change_case = PascalCase)]` /// /// ## Restrictions /// @@ -199,6 +200,7 @@ extern crate proc_macro; /// } /// # fn main() {} /// ```` +// END DOCS FROM classes.md #[proc_macro_attribute] pub fn php_class(args: TokenStream, input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as ItemStruct); @@ -211,6 +213,7 @@ pub fn php_class(args: TokenStream, input: TokenStream) -> TokenStream { .into() } +// BEGIN DOCS FROM function.md /// # `#[php_function]` Attribute /// /// Used to annotate functions which should be exported to PHP. Note that this @@ -365,6 +368,7 @@ pub fn php_class(args: TokenStream, input: TokenStream) -> TokenStream { /// You can also return a `Result` from the function. The error variant will be /// translated into an exception and thrown. See the section on /// [exceptions](../exceptions.md) for more details. +// END DOCS FROM function.md #[proc_macro_attribute] pub fn php_function(args: TokenStream, input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as ItemFn); @@ -377,6 +381,7 @@ pub fn php_function(args: TokenStream, input: TokenStream) -> TokenStream { .into() } +// BEGIN DOCS FROM constant.md /// # `#[php_const]` Attribute /// /// Exports a Rust constant as a global PHP constant. The constant can be any @@ -389,8 +394,8 @@ pub fn php_function(args: TokenStream, input: TokenStream) -> TokenStream { /// /// - `name` - Allows you to rename the property, e.g. `#[php(name = /// "new_name")]` -/// - `rename` - Allows you to rename the property using rename rules, e.g. -/// `#[php(rename = PascalCase)]` +/// - `change_case` - Allows you to rename the property using rename rules, e.g. +/// `#[php(change_case = PascalCase)]` /// /// ## Examples /// @@ -428,6 +433,7 @@ pub fn php_function(args: TokenStream, input: TokenStream) -> TokenStream { /// var_dump(I_AM_RENAMED); // int(42) /// var_dump(MANUAL_CONSTANT); // string(12) "Hello world!" /// ``` +// END DOCS FROM constant.md #[proc_macro_attribute] pub fn php_const(args: TokenStream, input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as ItemConst); @@ -440,6 +446,7 @@ pub fn php_const(args: TokenStream, input: TokenStream) -> TokenStream { .into() } +// BEGIN DOCS FROM module.md /// # `#[php_module]` Attribute /// /// The module macro is used to annotate the `get_module` function, which is @@ -506,6 +513,7 @@ pub fn php_const(args: TokenStream, input: TokenStream) -> TokenStream { /// } /// # fn main() {} /// ``` +// END DOCS FROM module.md #[proc_macro_attribute] pub fn php_module(args: TokenStream, input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as ItemFn); @@ -518,6 +526,7 @@ pub fn php_module(args: TokenStream, input: TokenStream) -> TokenStream { .into() } +// BEGIN DOCS FROM impl.md /// # `#[php_impl]` Attribute /// /// You can export an entire `impl` block to PHP. This exports all methods as @@ -532,6 +541,21 @@ pub fn php_module(args: TokenStream, input: TokenStream) -> TokenStream { /// If you want to use async Rust, use `#[php_async_impl]`, instead: see [here /// »](./async_impl.md) for more info. /// +/// ## Options +/// +/// By default all constants are renamed to `UPPER_CASE` and all methods are +/// renamed to camelCase. This can be changed by passing the +/// `change_method_case` and `change_constant_case` as `#[php]` attributes on +/// the `impl` block. The options are: +/// +/// - `#[php(change_method_case = "snake_case")]` - Renames the method to snake +/// case. +/// - `#[php(change_constant_case = "snake_case")]` - Renames the constant to +/// snake case. +/// +/// See the [`name` and `change_case`](./php.md#name-and-change_case) section +/// for a list of all available cases. +/// /// ## Methods /// /// Methods basically follow the same rules as functions, so read about the @@ -546,17 +570,6 @@ pub fn php_module(args: TokenStream, input: TokenStream) -> TokenStream { /// must be named `self_`. This can also be used to return a reference to /// `$this`. /// -/// By default, all methods are renamed in PHP to the camel-case variant of the -/// Rust method name. This can be changed on the `#[php_impl]` attribute, by -/// passing one of the following as the `rename_methods` option: -/// -/// - `"none"` - does not rename the methods. -/// - `"camelCase"` - renames all methods to camel case (default). -/// - `"snake_case"` - renames all methods to snake case. -/// -/// For example, to disable renaming, change the `#[php_impl]` attribute to -/// `#[php_impl(rename_methods = "none")]`. -/// /// The rest of the options are passed as separate attributes: /// /// - `#[php(defaults(i = 5, b = "hello")]` - Sets the default value for @@ -602,8 +615,9 @@ pub fn php_module(args: TokenStream, input: TokenStream) -> TokenStream { /// attributes. By default, the `get_` or `set_` prefix is trimmed from the /// start of the function name, and the remainder is used as the property name. /// -/// If you want to use a different name for the property, you can pass a -/// `rename` option to the attribute which will change the property name. +/// If you want to use a different name for the property, you can pass a `name` +/// or `change_case` option to the `#[php]` attribute which will change the +/// property name. /// /// Properties do not necessarily have to have both a getter and a setter, if /// the property is immutable the setter can be omitted, and vice versa for @@ -696,6 +710,7 @@ pub fn php_module(args: TokenStream, input: TokenStream) -> TokenStream { /// ``` /// /// [`php_async_impl`]: ./async_impl.md +// END DOCS FROM impl.md #[proc_macro_attribute] pub fn php_impl(args: TokenStream, input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as ItemImpl); @@ -708,6 +723,7 @@ pub fn php_impl(args: TokenStream, input: TokenStream) -> TokenStream { .into() } +// BEGIN DOCS FROM extern.md /// # `#[php_extern]` Attribute /// /// Attribute used to annotate `extern` blocks which are deemed as PHP @@ -771,6 +787,7 @@ pub fn php_impl(args: TokenStream, input: TokenStream) -> TokenStream { /// [`strpos`]: https://www.php.net/manual/en/function.strpos.php /// [`IntoZval`]: crate::convert::IntoZval /// [`Zval`]: crate::types::Zval +// END DOCS FROM extern.md #[proc_macro_attribute] pub fn php_extern(_: TokenStream, input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as ItemForeignMod); @@ -780,6 +797,7 @@ pub fn php_extern(_: TokenStream, input: TokenStream) -> TokenStream { .into() } +// BEGIN DOCS FROM zval_convert.md /// # `ZvalConvert` Derive Macro /// /// The `#[derive(ZvalConvert)]` macro derives the `FromZval` and `IntoZval` @@ -932,6 +950,7 @@ pub fn php_extern(_: TokenStream, input: TokenStream) -> TokenStream { /// test_union(null); // UnionExample::None /// var_dump(give_union()); // int(5) /// ``` +// END DOCS FROM zval_convert.md #[proc_macro_derive(ZvalConvert)] pub fn zval_convert_derive(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as DeriveInput); diff --git a/crates/macros/src/parsing.rs b/crates/macros/src/parsing.rs index 78443b50de..9577403481 100644 --- a/crates/macros/src/parsing.rs +++ b/crates/macros/src/parsing.rs @@ -43,7 +43,7 @@ pub trait MethodRename: Rename { #[darling(default)] pub struct PhpRename { name: Option, - rename: Option, + change_case: Option, } impl PhpRename { @@ -51,7 +51,7 @@ impl PhpRename { if let Some(name) = self.name.as_ref() { name.to_string() } else { - name.as_ref().rename(self.rename.unwrap_or(default)) + name.as_ref().rename(self.change_case.unwrap_or(default)) } } @@ -59,7 +59,8 @@ impl PhpRename { if let Some(name) = self.name.as_ref() { name.to_string() } else { - name.as_ref().rename_method(self.rename.unwrap_or(default)) + name.as_ref() + .rename_method(self.change_case.unwrap_or(default)) } } } @@ -139,7 +140,7 @@ mod tests { fn php_rename() { let rename = PhpRename { name: Some("test".to_string()), - rename: None, + change_case: None, }; assert_eq!(rename.rename("testCase", RenameRule::Snake), "test"); assert_eq!(rename.rename("TestCase", RenameRule::Snake), "test"); @@ -147,7 +148,7 @@ mod tests { let rename = PhpRename { name: None, - rename: Some(RenameRule::ScreamingSnake), + change_case: Some(RenameRule::ScreamingSnake), }; assert_eq!(rename.rename("testCase", RenameRule::Snake), "TEST_CASE"); assert_eq!(rename.rename("TestCase", RenameRule::Snake), "TEST_CASE"); @@ -155,7 +156,7 @@ mod tests { let rename = PhpRename { name: Some("test".to_string()), - rename: Some(RenameRule::ScreamingSnake), + change_case: Some(RenameRule::ScreamingSnake), }; assert_eq!(rename.rename("testCase", RenameRule::Snake), "test"); assert_eq!(rename.rename("TestCase", RenameRule::Snake), "test"); @@ -163,7 +164,7 @@ mod tests { let rename = PhpRename { name: None, - rename: None, + change_case: None, }; assert_eq!(rename.rename("testCase", RenameRule::Snake), "test_case"); assert_eq!(rename.rename("TestCase", RenameRule::Snake), "test_case"); @@ -174,7 +175,7 @@ mod tests { fn php_rename_method() { let rename = PhpRename { name: Some("test".to_string()), - rename: None, + change_case: None, }; assert_eq!(rename.rename_method("testCase", RenameRule::Snake), "test"); assert_eq!(rename.rename_method("TestCase", RenameRule::Snake), "test"); @@ -182,7 +183,7 @@ mod tests { let rename = PhpRename { name: None, - rename: Some(RenameRule::ScreamingSnake), + change_case: Some(RenameRule::ScreamingSnake), }; assert_eq!( rename.rename_method("testCase", RenameRule::Snake), @@ -199,7 +200,7 @@ mod tests { let rename = PhpRename { name: Some("test".to_string()), - rename: Some(RenameRule::ScreamingSnake), + change_case: Some(RenameRule::ScreamingSnake), }; assert_eq!(rename.rename_method("testCase", RenameRule::Snake), "test"); assert_eq!(rename.rename_method("TestCase", RenameRule::Snake), "test"); @@ -207,7 +208,7 @@ mod tests { let rename = PhpRename { name: None, - rename: None, + change_case: None, }; assert_eq!( rename.rename_method("testCase", RenameRule::Snake), @@ -249,7 +250,7 @@ mod tests { magic, PhpRename { name: None, - rename: Some(RenameRule::None) + change_case: Some(RenameRule::None) } .rename_method(magic, RenameRule::ScreamingSnake) ); @@ -259,7 +260,7 @@ mod tests { expected, PhpRename { name: None, - rename: Some(RenameRule::Camel) + change_case: Some(RenameRule::Camel) } .rename_method(magic, RenameRule::ScreamingSnake) ); @@ -269,7 +270,7 @@ mod tests { expected, PhpRename { name: None, - rename: Some(RenameRule::Pascal) + change_case: Some(RenameRule::Pascal) } .rename_method(magic, RenameRule::ScreamingSnake) ); @@ -279,7 +280,7 @@ mod tests { expected, PhpRename { name: None, - rename: Some(RenameRule::Snake) + change_case: Some(RenameRule::Snake) } .rename_method(magic, RenameRule::ScreamingSnake) ); @@ -289,7 +290,7 @@ mod tests { expected, PhpRename { name: None, - rename: Some(RenameRule::ScreamingSnake) + change_case: Some(RenameRule::ScreamingSnake) } .rename_method(magic, RenameRule::Camel) ); diff --git a/guide/src/macros/classes.md b/guide/src/macros/classes.md index e27124d895..4ea14c8f32 100644 --- a/guide/src/macros/classes.md +++ b/guide/src/macros/classes.md @@ -12,7 +12,7 @@ placed underneath the `#[php_class]` attribute. - `name` - Changes the name of the class when exported to PHP. The Rust struct name is kept the same. If no name is given, the name of the struct is used. Useful for namespacing classes. -- `rename` - Changes the case of the class name when exported to PHP. +- `change_case` - Changes the case of the class name when exported to PHP. - `#[php(extends(ce = ce_fn, stub = "ParentClass"))]` - Sets the parent class of the class. Can only be used once. `ce_fn` must be a function with the signature `fn() -> &'static ClassEntry`. - `#[php(implements(ce = ce_fn, stub = "InterfaceName"))]` - Implements the given interface on the class. Can be used @@ -28,8 +28,8 @@ You can rename the property with options: - `name` - Allows you to rename the property, e.g. `#[php(name = "new_name")]` -- `rename` - Allows you to rename the property using rename rules, e.g. - `#[php(rename = PascalCase)]` +- `change_case` - Allows you to rename the property using rename rules, e.g. + `#[php(change_case = PascalCase)]` ## Restrictions @@ -121,7 +121,7 @@ pub fn get_module(module: ModuleBuilder) -> ModuleBuilder { To implement an interface, use `#[php(implements(ce = ce_fn, stub = "InterfaceName")]` where `ce_fn` is an function returning a `ClassEntry`. The following example implements [`ArrayAccess`](https://www.php.net/manual/en/class.arrayaccess.php): -```rust,no_run +````rust,no_run # #![cfg_attr(windows, feature(abi_vectorcall))] # extern crate ext_php_rs; use ext_php_rs::{ diff --git a/guide/src/macros/constant.md b/guide/src/macros/constant.md index 99dee3f0e9..91f5a60a8b 100644 --- a/guide/src/macros/constant.md +++ b/guide/src/macros/constant.md @@ -10,8 +10,8 @@ You can rename the const with options: - `name` - Allows you to rename the property, e.g. `#[php(name = "new_name")]` -- `rename` - Allows you to rename the property using rename rules, e.g. - `#[php(rename = PascalCase)]` +- `change_case` - Allows you to rename the property using rename rules, e.g. + `#[php(change_case = PascalCase)]` ## Examples diff --git a/guide/src/macros/impl.md b/guide/src/macros/impl.md index 46ac3bffa8..534cb35bd3 100644 --- a/guide/src/macros/impl.md +++ b/guide/src/macros/impl.md @@ -13,14 +13,14 @@ If you want to use async Rust, use `#[php_async_impl]`, instead: see [here &raqu ## Options -By default all constants are renamed to UPPER_CASE and all methods are renamed to -camelCase. This can be changed by passing the `rename_methods` and -`rename_constants` as `#[php]` attributes on the `impl` block. The options are: +By default all constants are renamed to `UPPER_CASE` and all methods are renamed to +camelCase. This can be changed by passing the `change_method_case` and +`change_constant_case` as `#[php]` attributes on the `impl` block. The options are: -- `#[php(rename_methods = "snake_case")]` - Renames the method to snake case. -- `#[php(rename_constants = "snake_case")]` - Renames the constant to snake case. +- `#[php(change_method_case = "snake_case")]` - Renames the method to snake case. +- `#[php(change_constant_case = "snake_case")]` - Renames the constant to snake case. -See the [`name` and `rename`](./php.md#name-and-rename) section for a list of all +See the [`name` and `change_case`](./php.md#name-and-change_case) section for a list of all available cases. ## Methods @@ -79,8 +79,8 @@ setters. This is done with the `#[php(getter)]` and `#[php(setter)]` attributes. default, the `get_` or `set_` prefix is trimmed from the start of the function name, and the remainder is used as the property name. -If you want to use a different name for the property, you can pass a `rename` -option to the attribute which will change the property name. +If you want to use a different name for the property, you can pass a `name` or +`change_case` option to the `#[php]` attribute which will change the property name. Properties do not necessarily have to have both a getter and a setter, if the property is immutable the setter can be omitted, and vice versa for getters. diff --git a/guide/src/macros/php.md b/guide/src/macros/php.md index ad0331365d..0e52ff0117 100644 --- a/guide/src/macros/php.md +++ b/guide/src/macros/php.md @@ -33,33 +33,33 @@ fn hello_world(a: i32, b: i32) -> i32 { Which attributes are available depends on the element you are annotating: -| Attribute | `const` | `fn` | `struct` | `struct` Field | `impl` | `impl` `const` | `impl` `fn` | -| ---------------- | ------- | ---- | -------- | -------------- | ------ | -------------- | ----------- | -| name | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | -| rename | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | -| rename_methods | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | -| rename_constants | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | -| flags | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | -| prop | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | -| extends | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | -| implements | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | -| modifier | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | -| defaults | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | -| optional | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | -| vis | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | -| getter | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | -| setter | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | -| constructor | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | -| abstract_method | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | +| Attribute | `const` | `fn` | `struct` | `struct` field | `impl` | `impl` `const` | `impl` `fn` | +| -------------------- | ------- | ---- | -------- | -------------- | ------ | -------------- | ----------- | +| name | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | +| change_case | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | +| change_method_case | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | +| change_constant_case | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | +| flags | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | +| prop | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | +| extends | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | +| implements | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | +| modifier | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | +| defaults | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | +| optional | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | +| vis | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | +| getter | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | +| setter | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | +| constructor | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | +| abstract_method | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | -## `name` and `rename` +## `name` and `change_case` -`name` and `rename` are mutually exclusive. The `name` attribute is used to set the name of -an item to a string literal. The `rename` attribute is used to change the case of the name. +`name` and `change_case` are mutually exclusive. The `name` attribute is used to set the name of +an item to a string literal. The `change_case` attribute is used to change the case of the name. ```rs #[php(name = "NEW_NAME")] -#[php(rename = snake_case)]] +#[php(change_case = snake_case)]] ``` Available cases are: diff --git a/guide/src/migration-guides/v0.14.md b/guide/src/migration-guides/v0.14.md index 429158e550..8db4abe5d1 100644 --- a/guide/src/migration-guides/v0.14.md +++ b/guide/src/migration-guides/v0.14.md @@ -47,7 +47,7 @@ pub fn get_module(module: ModuleBuilder) -> ModuleBuilder { **Supported `#[php]` attributes:** - `#[php(name = "NEW_NAME")]` - Renames the function -- `#[php(rename = case)]` - Changes the case of the function name +- `#[php(change_case = case)]` - Changes the case of the function name - `#[php(vis = "public")]` - Changes the visibility of the function - `#[php(defaults(a = 5, test = 100))]` - Sets default values for function arguments - `#[php(variadic)]` - Marks the function as variadic. The last argument must be a `&[&Zval]` @@ -104,15 +104,15 @@ pub fn get_module(module: ModuleBuilder) -> ModuleBuilder { **Supported `#[php]` attributes (`struct`):** - `#[php(name = "NEW_NAME")]` - Renames the class -- `#[php(rename = case)]` - Changes the case of the class name +- `#[php(change_case = case)]` - Changes the case of the class name - `#[php(vis = "public")]` - Changes the visibility of the class - `#[php(extends(ce = ce_fn, stub = "ParentClass")]` - Extends a parent class - `#[php(implements(ce = ce_fn, stub = "Interface"))]` - Implements an interface - `#[php(prop)]` - Marks a field as a property **Supported `#[php]` attributes (`impl`):** -- `#[php(rename_consts = case)]` - Changes the case of the constant names. Can be overridden by attributes on the constants. -- `#[php(rename_methods = case)]` - Changes the case of the method names. Can be overridden by attributes on the methods. +- `#[php(change_constant_case = case)]` - Changes the case of the constant names. Can be overridden by attributes on the constants. +- `#[php(change_method_case = case)]` - Changes the case of the method names. Can be overridden by attributes on the methods. For elements in the `#[php_impl]` block see the respective function and constant attributes. @@ -149,7 +149,7 @@ pub fn get_module(module: ModuleBuilder) -> ModuleBuilder { **Supported `#[php]` attributes:** - `#[php(name = "NEW_NAME")]` - Renames the constant -- `#[php(rename = case)]` - Changes the case of the constant name +- `#[php(change_case = case)]` - Changes the case of the constant name - `#[php(vis = "public")]` - Changes the visibility of the constant ### Extern @@ -196,12 +196,12 @@ Attributes like `#[rename]` or `#[prop]` have been moved to the `#[php]` attribu The `#[php]` attribute on an item are combined with each other. This means that the following variants are equivalent: ```rs -#[php(rename = case)] +#[php(change_case = case)] #[php(vis = "public")] ``` ```rs -#[php(rename = case, vis = "public")] +#[php(change_case = case, vis = "public")] ``` ### Renaming and Case Changes @@ -213,19 +213,19 @@ Default case was adjusted to match PSR standards: - Constant names are now `UPPER_CASE` - Function names are now `snake_case` -This can be changed using the `rename` attribute on the item. -Additionally, the `rename_methods` and `rename_consts` attributes can be used +This can be changed using the `change_case` attribute on the item. +Additionally, the `change_method_case` and `change_constant_case` attributes can be used to change the case of all methods and constants in a class. -#### `name` vs `rename` +#### `name` vs `change_case` Previously the (re)name parameter was used to rename items. This has been unified to use `name` to set the name of an item to a string literal. The -`rename` parameter is now used to change the case of the name. +`change_case` parameter is now used to change the case of the name. ```rs #[php(name = "NEW_NAME")] -#[php(rename = snake_case)]] +#[php(change_case = snake_case)]] ``` Available cases are: diff --git a/tools/update_lib_docs.sh b/tools/update_lib_docs.sh new file mode 100755 index 0000000000..d45d0e6181 --- /dev/null +++ b/tools/update_lib_docs.sh @@ -0,0 +1,55 @@ +#!/bin/bash +### This script updates the documentation in the macros library by copying +### the content from the guide files into the macros library source code. +### +### This is needed, because importing them using the `#[doc]` attribute +### does not work with rust analyser, which is used by the IDEs. +### https://github.com/rust-lang/rust-analyzer/issues/11137 + +set -e + +# Check if the script is run from the root directory +if [ ! -f "tools/update_lib_docs.sh" ]; then + echo "Please run this script from the root directory of the project." + exit 1 +fi + +function update_docs() { + file_name="$1.md" + + if [ ! -f "guide/src/macros/$file_name" ]; then + echo "File guide/src/macros/$file_name does not exist." + exit 1 + fi + + if ! grep -q "// BEGIN DOCS FROM $file_name" "crates/macros/src/lib.rs"; then + echo "No start placeholder found for $file_name in crates/macros/src/lib.rs." + exit 1 + fi + + if ! grep -q "// END DOCS FROM $file_name" "crates/macros/src/lib.rs"; then + echo "No end placeholder found for $file_name in crates/macros/src/lib.rs." + exit 1 + fi + + lead="^\/\/ BEGIN DOCS FROM $file_name$" + tail="^\/\/ END DOCS FROM $file_name$" + + # Make content a doc comment + sed -e "s/^/\/\/\/ /" "guide/src/macros/$file_name" | + # Disable doc tests for the pasted content + sed -e "s/rust,no_run/rust,no_run,ignore/" | + # Replace the section in the macros library with the content from the guide + sed -i -e "/$lead/,/$tail/{ /$lead/{p; r /dev/stdin" -e "}; /$tail/p; d }" "crates/macros/src/lib.rs" +} + +update_docs "classes" +update_docs "constant" +update_docs "extern" +update_docs "function" +update_docs "impl" +update_docs "module" +update_docs "zval_convert" + +# Format to remove trailing whitespace +rustup run nightly rustfmt crates/macros/src/lib.rs From 5dc852563191aa71ebe7dd9481fd0c4ce32d7102 Mon Sep 17 00:00:00 2001 From: Xenira <1288524+Xenira@users.noreply.github.com> Date: Tue, 1 Jul 2025 17:09:21 +0200 Subject: [PATCH 2/2] chore(hooks): add check for outdated macro documentation Refs: #466 --- .github/workflows/macro_docs.yml | 30 ++++++++++++++++++++++++++++++ .lefthook.yml | 9 +++++++++ CONTRIBUTING.md | 2 ++ 3 files changed, 41 insertions(+) create mode 100644 .github/workflows/macro_docs.yml diff --git a/.github/workflows/macro_docs.yml b/.github/workflows/macro_docs.yml new file mode 100644 index 0000000000..e82acb9921 --- /dev/null +++ b/.github/workflows/macro_docs.yml @@ -0,0 +1,30 @@ +name: macro docs +on: + pull_request: + paths: + - "guide/src/macros/*.md" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + lint-bindings: + name: Lint bindings + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup Rust + uses: dtolnay/rust-toolchain@master + with: + components: rustfmt + toolchain: nightly + - name: Cache cargo dependencies + uses: Swatinem/rust-cache@v2 + with: + prefix-key: ${{ env.RUST_CACHE_PREFIX }} + - name: Macro docs + run: tools/update_lib_docs.sh && git diff --exit-code crates/macros/src/lib.rs diff --git a/.lefthook.yml b/.lefthook.yml index bed0049caf..14d6d4e693 100644 --- a/.lefthook.yml +++ b/.lefthook.yml @@ -11,3 +11,12 @@ pre-commit: - name: bindings run: tools/update_bindings.sh && git diff --exit-code docsrs_bindings.rs glob: "allowed_bindings.rs" + fail_text: | + The `docsrs_bindings.rs` file seems to be out of date. + Please check the updated bindings in `docsrs_bindings.rs` and commit the changes. + - name: "macro docs" + run: tools/update_lib_docs.sh && git diff --exit-code crates/macros/src/lib.rs + glob: "guide/src/macros/*.md" + fail_text: | + The macro crates documentation seems to be out of date. + Please check the updated documentation in `crates/macros/src/lib.rs` and commit the changes. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 30b8a33fae..8b180ad239 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,6 +28,8 @@ lefthook install - When changing the `allowed_bindings.rs`, you need to have `docker` and `buildx` installed. This is required to build the bindings in a consistent environment. See the [installation guide](https://docs.docker.com/engine/install/) for instructions on how to install Docker. +- When updating the macro guides (`guide/src/macros`), you need to have the `nightly` toolchain installed. This is required + to have the proper formatting in the documentation. ## Testing