Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/macro_docs.yml
Original file line number Diff line number Diff line change
@@ -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
9 changes: 9 additions & 0 deletions .lefthook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
24 changes: 13 additions & 11 deletions crates/macros/src/impl_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ enum MethodTy {
#[darling(attributes(php), default)]
pub struct PhpImpl {
/// Rename methods to match the given rule.
rename_methods: Option<RenameRule>,
change_method_case: Option<RenameRule>,
/// Rename constants to match the given rule.
rename_constants: Option<RenameRule>,
change_constant_case: Option<RenameRule>,
}

pub fn parser(mut input: ItemImpl) -> Result<TokenStream> {
Expand All @@ -47,8 +47,9 @@ pub fn parser(mut input: ItemImpl) -> Result<TokenStream> {

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())?;

Expand Down Expand Up @@ -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<FnBuilder>,
constructor: Option<Function<'a>>,
constants: Vec<Constant<'a>>,
Expand Down Expand Up @@ -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(),
Expand All @@ -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"));

Expand All @@ -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"));

Expand Down
55 changes: 37 additions & 18 deletions crates/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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`.
Expand All @@ -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
///
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -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
///
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -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
/// &raquo;](./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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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`
Expand Down Expand Up @@ -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);
Expand Down
Loading