diff --git a/.github/actions/verify-generated/action.yml b/.github/actions/verify-generated/action.yml new file mode 100644 index 0000000..feb02ab --- /dev/null +++ b/.github/actions/verify-generated/action.yml @@ -0,0 +1,23 @@ +name: verify-generated +inputs: + working-directory: + required: true + extra-pathspec: + required: true +runs: + using: composite + steps: + - name: Run git add for untracked files + shell: bash + run: git add -N . + working-directory: ${{ inputs.working-directory }} + + - name: Show git status + shell: bash + run: git status + working-directory: ${{ inputs.working-directory }} + + - name: Check for changed files + shell: bash + run: git diff -a --exit-code HEAD -- "${{ inputs.extra-pathspec }}" + working-directory: ${{ inputs.working-directory }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b6f4484..3aa6cb0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -83,9 +83,19 @@ jobs: working-directory: ./php/php-src/ext/rust-ext - name: Run clippy on example + # Run clippy for the example even if for the main project it failed + if: ${{ !cancelled() }} run: cargo clippy --all-targets --all-features -- -Dwarnings working-directory: ./php/php-src/ext/rust-ext/example/rust-ext-demo + - name: Check generated files + # Run check even if clippy or something else failed + if: ${{ !cancelled() }} + uses: ./php/php-src/ext/rust-ext/.github/actions/verify-generated + with: + working-directory: php/php-src/ext/rust-ext + extra-pathspec: ':(exclude)crates/sys/bindings.rs' + test: name: > Run tests (${{ matrix.php }}, diff --git a/crates/stub-parser/src/builder.rs b/crates/stub-parser/src/builder.rs index 75327e3..09fe291 100644 --- a/crates/stub-parser/src/builder.rs +++ b/crates/stub-parser/src/builder.rs @@ -1,6 +1,7 @@ use crate::VerificationMode; +use crate::imports::ImportsUsed; use crate::types::ArgInfoTypeRepr; -use crate::verification::VerificationData; +use crate::verification::{VERIFICATION_RSPHP_SYS_IMPORTS, VerificationData}; use php_ast::ast::{BuiltinType, Visibility}; use php_ast::owned::{ Attribute, ClassConstDecl, ClassDecl, ClassMemberKind, Comment, EnumCase, EnumDecl, @@ -10,6 +11,7 @@ use php_ast::owned::{ use php_ast::span::Span; use regex::Regex; use std::assert_matches; +use std::collections::HashSet; use std::fmt::Write as _; /// Wrapper around `EnumDecl`, `ClassDecl`, or `InterfaceDecl` to present a @@ -140,11 +142,12 @@ impl ClassLikeType { /// interfaces that it should, with the assumption that the interfaces /// are available under the names from [`Self::interface_variables()`], and the /// overall class entry is available under the name `class_entry`. - fn interfaces_applied_code(&self) -> String { + fn interfaces_applied_code(&self, scope: &mut ImportsUsed) -> String { let interface_ptrs = self.interface_variables(); if interface_ptrs.is_empty() { String::new() } else { + scope.add_import("rsphp_sys", "zend_class_implements"); format!( "\n{space}unsafe {{\ \n{space}{space}zend_class_implements(\ @@ -163,9 +166,9 @@ impl ClassLikeType { /// the given number of methods, is in the given namespace, and the overall /// program where the class is declared is passed to allow fetching /// unprocessed details. - #[expect(clippy::too_many_lines, reason = "It's a complicated function")] fn init_and_register_code( &self, + scope: &mut ImportsUsed, namespace: Option<&String>, method_count: usize, program: &str, @@ -175,16 +178,16 @@ impl ClassLikeType { Some(ns) => format!("{ns}\\\\"), None => String::new(), }; - let add_interfaces = self.interfaces_applied_code(); - let init_macro = match (namespace, method_count) { - (Some(ns), 0) => format!("INIT_NS_CLASS_ENTRY!(ce, \"{ns}\", \"{name}\", NULL);"), - (Some(ns), _) => { - format!("INIT_NS_CLASS_ENTRY!(ce, \"{ns}\", \"{name}\", methods);") - } - (None, 0) => format!("INIT_CLASS_ENTRY!(ce, \"{name}\", NULL);"), - (None, _) => format!("INIT_CLASS_ENTRY!(ce, \"{name}\", methods);"), + let (macro_name, macro_ns_arg) = match namespace { + Some(ns) => ("INIT_NS_CLASS_ENTRY", format!(" \"{ns}\",")), + None => ("INIT_CLASS_ENTRY", String::new()), }; - match self { + let init_macro = format!( + "rsphp_macros_c::{macro_name}!(ce,{macro_ns_arg} \"{name}\", {methods});", + methods = if method_count == 0 { "NULL" } else { "methods" } + ); + scope.add_import("rsphp_sys", "zend_class_entry"); + let result = match self { ClassLikeType::Class(class) => { let extends_param = self .parent_class_var() @@ -192,16 +195,16 @@ impl ClassLikeType { let mut flags = vec![]; if class.modifiers.is_final { flags.push("ZEND_ACC_FINAL"); + scope.add_import("rsphp_sys", "ZEND_ACC_FINAL"); } - match class.doc_comment.as_ref() { - None => (), - Some(comment) => { - if comment.text.contains("@strict-properties") { - flags.push("ZEND_ACC_NO_DYNAMIC_PROPERTIES"); - } - if comment.text.contains("@not-serializable") { - flags.push("ZEND_ACC_NOT_SERIALIZABLE"); - } + if let Some(comment) = class.doc_comment.as_ref() { + if comment.text.contains("@strict-properties") { + flags.push("ZEND_ACC_NO_DYNAMIC_PROPERTIES"); + scope.add_import("rsphp_sys", "ZEND_ACC_NO_DYNAMIC_PROPERTIES"); + } + if comment.text.contains("@not-serializable") { + flags.push("ZEND_ACC_NOT_SERIALIZABLE"); + scope.add_import("rsphp_sys", "ZEND_ACC_NOT_SERIALIZABLE"); } } let flags_str = if flags.is_empty() { @@ -209,19 +212,18 @@ impl ClassLikeType { } else { flags.join("|") }; - Ok(format!( + format!( "\n{space}let mut ce: zend_class_entry = unsafe {{ std::mem::zeroed() }};\ \n{space}{init_macro}\ \n{space}let class_entry: *mut zend_class_entry = unsafe {{\ - \n{space}{space}zend_register_internal_class_with_flags(\ + \n{space}{space}rsphp_sys::zend_register_internal_class_with_flags(\ \n{space}{space}{space}std::ptr::from_mut::(&mut ce),\ \n{space}{space}{space}{extends_param},\ \n{space}{space}{space}{flags_str},\ \n{space}{space})\ - \n{space}}};\ - {add_interfaces}", + \n{space}}};", space = " ", - )) + ) } ClassLikeType::PhpEnum(php_enum) => { if method_count != 0 { @@ -232,47 +234,40 @@ impl ClassLikeType { let end: usize = span.end.try_into().expect("Valid usize"); program.get(start..end).expect("Valid byte range for span") }; - let backing = php_enum - .scalar_type - .as_ref() - .map(|type_name| match get_raw_code(type_name.span) { - "string" => Ok(BuiltinType::String), - "int" => Ok(BuiltinType::Int), - _ => Err(format!("Unhandled enum backing type for enum {self:#?}")), - }) - .transpose()?; - let backing_type_code = match backing { + let backing_type_code = match php_enum.scalar_type.as_ref() { None => "IS_UNDEF", - Some(BuiltinType::String) => "IS_STRING", - Some(BuiltinType::Int) => "IS_LONG", - Some(backing_type) => { - return Err(format!("Invalid backing type: {backing_type:?}")); - } + Some(type_name) => match get_raw_code(type_name.span) { + "string" => "IS_STRING", + "int" => "IS_LONG", + _ => return Err(format!("Unhandled enum backing type for enum {self:#?}")), + }, }; - Ok(format!( + scope.add_import("rsphp_sys", backing_type_code); + format!( "\n{space}let class_entry: *mut zend_class_entry = unsafe {{\ - \n{space}{space}zend_register_internal_enum(\ + \n{space}{space}rsphp_sys::zend_register_internal_enum(\ \n{space}{space}{space}c\"{ns_name_segment}{name}\".as_ptr(),\ \n{space}{space}{space}{backing_type_code},\ \n{space}{space}{space}std::ptr::null_mut(),\ \n{space}{space})\ - \n{space}}};\ - {add_interfaces}", + \n{space}}};", space = " ", - )) + ) } - ClassLikeType::Interface(_) => Ok(format!( - "\n{space}let mut ce: zend_class_entry = unsafe {{ std::mem::zeroed() }};\ - \n{space}{init_macro}\ - \n{space}let class_entry: *mut zend_class_entry = unsafe {{\ - \n{space}{space}zend_register_internal_interface(\ - \n{space}{space}{space}std::ptr::from_mut::(&mut ce),\ - \n{space}{space})\ - \n{space}}};\ - {add_interfaces}", - space = " ", - )), - } + ClassLikeType::Interface(_) => { + format!( + "\n{space}let mut ce: zend_class_entry = unsafe {{ std::mem::zeroed() }};\ + \n{space}{init_macro}\ + \n{space}let class_entry: *mut zend_class_entry = unsafe {{\ + \n{space}{space}rsphp_sys::zend_register_internal_interface(\ + \n{space}{space}{space}std::ptr::from_mut::(&mut ce),\ + \n{space}{space})\ + \n{space}}};", + space = " ", + ) + } + }; + Ok(result + &self.interfaces_applied_code(scope)) } /// The kind of class-like-type this is, one of "enum", "interface", or /// "class". @@ -303,6 +298,13 @@ pub(crate) struct ArgInfoBuilder<'program> { namespace: Option, /// How registration functions should verify their arguments. verification: VerificationMode, + /// Whether any class/enum/interface/trait is present in the stub; if not + /// then there is nothing to verify and the verification code doesn't need + /// to be added. + needs_verification: bool, + /// Imports used in the current level - replace this while in a different + /// scope. + scope: ImportsUsed, } impl<'program> ArgInfoBuilder<'program> { @@ -314,15 +316,13 @@ impl<'program> ArgInfoBuilder<'program> { parts: vec![], namespace: None, verification, + needs_verification: false, + scope: ImportsUsed::new(), } } } -#[expect( - clippy::unused_self, - clippy::needless_pass_by_ref_mut, - reason = "Non-wildcard imports not set up yet" -)] +#[expect(clippy::too_many_lines, reason = "Many complicated functions")] impl ArgInfoBuilder<'_> { /// Get a snippet of the raw code in the program at the location specified /// in the span. @@ -338,12 +338,23 @@ impl ArgInfoBuilder<'_> { for stmt in statements { match &stmt.kind { StmtKind::Function(function) => self.function(function.as_ref())?, - StmtKind::Class(class) => self.class_like(&ClassLikeType::Class(*class.clone()))?, + StmtKind::Class(class) => { + let old_scope = std::mem::take(&mut self.scope); + let result = self.class_like(&ClassLikeType::Class(*class.clone())); + self.scope = old_scope; + result?; + } StmtKind::Enum(php_enum) => { - self.class_like(&ClassLikeType::PhpEnum(*php_enum.clone()))?; + let old_scope = std::mem::take(&mut self.scope); + let result = self.class_like(&ClassLikeType::PhpEnum(*php_enum.clone())); + self.scope = old_scope; + result?; } StmtKind::Interface(interface) => { - self.class_like(&ClassLikeType::Interface(*interface.clone()))?; + let old_scope = std::mem::take(&mut self.scope); + let result = self.class_like(&ClassLikeType::Interface(*interface.clone())); + self.scope = old_scope; + result?; } StmtKind::Namespace(namespace) => self.namespace(namespace.as_ref())?, _ => (), @@ -379,12 +390,11 @@ impl ArgInfoBuilder<'_> { /// Generate code for a function parameter. fn param(&mut self, param: &Param) -> Result { let by_ref = u8::from(param.by_ref); - let param_type_info = param.type_hint.as_ref().map(|type_hint| { - let th = ArgInfoTypeRepr::try_from(type_hint.kind.clone(), self.namespace.as_ref()) + let param_type_info_opt = param.type_hint.as_ref().map(|type_hint| { + ArgInfoTypeRepr::try_from(type_hint.kind.clone(), self.namespace.as_ref()) .expect("Type representation should be valid") .typehint(self.namespace.as_ref()) - .expect("Type representation should work for parameters"); - (th.class_info, th.mask_info, th.return_info, th.is_nullable) + .expect("Type representation should work for parameters") }); let name = param .name @@ -407,57 +417,92 @@ impl ArgInfoBuilder<'_> { default = None; } let maybe_variadic = if param.variadic { "VARIADIC_" } else { "" }; - #[expect(clippy::uninlined_format_args, reason = "Clearer to not inline")] - let macro_result = match (param_type_info, default) { - (None, None) => format!( - "ZEND_ARG_{v}INFO!({by_ref}, \"{name}\")", - v = maybe_variadic + let Some(param_type_info) = param_type_info_opt else { + let (macro_name, macro_args) = match default { + None => ( + format!("ZEND_ARG_{maybe_variadic}INFO"), + format!("({by_ref}, \"{name}\")"), + ), + Some(dflt) => ( + "ZEND_ARG_INFO_WITH_DEFAULT_VALUE".to_owned(), + format!("({by_ref}, \"{name}\", \"{dflt}\")"), + ), + }; + self.scope.add_import("rsphp_macros_c", macro_name.clone()); + return Ok(format!(" {macro_name}!{macro_args},\n")); + }; + let (macro_name, macro_args) = match ( + ( + param_type_info.class_info, + param_type_info.mask_info, + param_type_info.return_info, + param_type_info.is_nullable, ), - (None, Some(dflt)) => { - format!("ZEND_ARG_INFO_WITH_DEFAULT_VALUE!({by_ref}, \"{name}\", \"{dflt}\")") - } - (Some((None, None, _, _)), _) => { + default, + ) { + ((None, None, _, _), _) => { return Err(format!("No class or type mask for {param:?}")); } - (Some((None, Some(param_mask), param_info, nullable)), None) => { + ((None, Some(param_mask), param_info, nullable), None) => { if param_mask.contains('|') { - format!( - "ZEND_ARG_TYPE_MASK!({by_ref}, \"{name}\", {param_mask}, std::ptr::null())", + self.scope.extend_sys_imports(param_type_info.mask_uses); + ( + "ZEND_ARG_TYPE_MASK".to_owned(), + format!("({by_ref}, \"{name}\", {param_mask}, std::ptr::null())"), ) } else { - format!( - "ZEND_ARG_{v}TYPE_INFO!({by_ref}, \"{name}\", {}, {})", - param_info.expect("Should be set"), - u8::from(nullable), - v = maybe_variadic, + self.scope.extend_sys_imports(param_type_info.return_uses); + ( + format!("ZEND_ARG_{maybe_variadic}TYPE_INFO"), + format!( + "({by_ref}, \"{name}\", {}, {})", + param_info.expect("Should be set"), + u8::from(nullable), + ), ) } } - (Some((Some(param_class), None, None, nullable)), None) => format!( - "ZEND_ARG_{v}OBJ_INFO!({by_ref}, \"{name}\", \"{param_class}\", {})", - u8::from(nullable), - v = maybe_variadic, - ), - (Some((Some(param_class), Some(param_mask), _, _)), dflt) => format!( - "ZEND_ARG_{v}OBJ_TYPE_MASK!({by_ref}, \"{name}\", \"{param_class}\", {param_mask}, {})", - match dflt { - Some(default_repr) => default_repr, - None => "NULL".to_owned(), - }, - v = maybe_variadic, - ), - (Some((None, _, Some(param_info), nullable)), Some(dflt)) => format!( - "ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE!({by_ref}, \"{name}\", {param_info}, {}, \"{dflt}\")", - u8::from(nullable), + ((Some(param_class), None, None, nullable), None) => ( + format!("ZEND_ARG_{maybe_variadic}OBJ_INFO"), + format!( + "({by_ref}, \"{name}\", \"{param_class}\", {})", + u8::from(nullable), + ), ), - (Some((Some(param_class), None, None, nullable)), Some(dflt)) => format!( - "ZEND_ARG_{v}OBJ_INFO_WITH_DEFAULT_VALUE!({by_ref}, \"{name}\", \"{param_class}\", {}, \"{dflt}\")", - u8::from(nullable), - v = maybe_variadic, + ((Some(param_class), Some(param_mask), _, _), dflt) => { + self.scope.extend_sys_imports(param_type_info.mask_uses); + ( + format!("ZEND_ARG_{maybe_variadic}OBJ_TYPE_MASK"), + format!( + "({by_ref}, \"{name}\", \"{param_class}\", {param_mask}, {})", + match dflt { + Some(default_repr) => default_repr, + None => "NULL".to_owned(), + }, + ), + ) + } + ((None, _, Some(param_info), nullable), Some(dflt)) => { + self.scope.extend_sys_imports(param_type_info.return_uses); + ( + "ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE".to_owned(), + format!( + "({by_ref}, \"{name}\", {param_info}, {}, \"{dflt}\")", + u8::from(nullable), + ), + ) + } + ((Some(param_class), None, None, nullable), Some(dflt)) if !param.variadic => ( + "ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE".to_owned(), + format!( + "({by_ref}, \"{name}\", \"{param_class}\", {}, \"{dflt}\")", + u8::from(nullable), + ), ), _ => return Err(format!("Unhandled parameter: {param:?}")), }; - Ok(format!(" {macro_result},\n")) + self.scope.add_import("rsphp_macros_c", macro_name.clone()); + Ok(format!(" {macro_name}!{macro_args},\n")) } /// Generate code for a global function or class method. @@ -482,6 +527,9 @@ impl ArgInfoBuilder<'_> { .collect::, _>>()?; let return_reference_int: u8 = u8::from(return_reference); let Some(return_info) = return_type else { + self.scope.add_import("rsphp_sys", "zend_internal_arg_info"); + self.scope + .add_import("rsphp_macros_rs", "ZEND_ARG_INFO_FOR_FUNCTION"); return Ok(format!( "/// Argument information for `{doc_name}()`.\ \npub(crate) const {name_constant}: [zend_internal_arg_info; {}] = [\ @@ -503,34 +551,57 @@ impl ArgInfoBuilder<'_> { }; let tentative_int = u8::from(tentative); #[expect(clippy::uninlined_format_args, reason = "Clearer to not inline")] - let fn_arginfo = match ( + let (fn_arginfo_macro, fn_arginfo_params) = match ( typehint.class_info, typehint.mask_info, typehint.return_info, ) { (None, None, None) => return Err(format!("No return info for {return_info:?}")), - (Some(class), None, None) => format!( - "ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_OBJ_INFO!({}, {}, \"{}\", {}, {})", - return_reference_int, required_params, class, ret_nullable, tentative_int, - ), - (None, _, Some(info)) if typehint.is_nullable => format!( - "ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_INFO!({}, {}, {}, 1, {})", - return_reference_int, required_params, info, tentative_int, - ), - (None, Some(mask), _) => format!( - "ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK!({}, {}, {}, {})", - return_reference_int, required_params, mask, tentative_int, - ), - (Some(class), Some(mask), _) => format!( - "ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_OBJ_TYPE_INFO!({}, {}, \"{}\", {}, {})", - return_reference_int, required_params, class, mask, tentative_int, + (Some(class), None, None) => ( + "ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_OBJ_INFO", + format!( + "({}, {}, \"{}\", {}, {})", + return_reference_int, required_params, class, ret_nullable, tentative_int, + ), ), + (None, _, Some(info)) if typehint.is_nullable => { + self.scope.extend_sys_imports(typehint.return_uses); + ( + "ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_INFO", + format!( + "({}, {}, {}, 1, {})", + return_reference_int, required_params, info, tentative_int, + ), + ) + } + (None, Some(mask), _) => { + self.scope.extend_sys_imports(typehint.mask_uses); + ( + "ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK", + format!( + "({}, {}, {}, {})", + return_reference_int, required_params, mask, tentative_int, + ), + ) + } + (Some(class), Some(mask), _) => { + self.scope.extend_sys_imports(typehint.mask_uses); + ( + "ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_OBJ_TYPE_INFO", + format!( + "({}, {}, \"{}\", {}, {})", + return_reference_int, required_params, class, mask, tentative_int, + ), + ) + } _ => return Err(format!("Unhandled return info: {return_info:?}")), }; + self.scope.add_import("rsphp_sys", "zend_internal_arg_info"); + self.scope.add_import("rsphp_macros_rs", fn_arginfo_macro); Ok(format!( "/// Argument information for `{doc_name}()`.\ \npub(crate) const {name_constant}: [zend_internal_arg_info; {}] = [\ - \n{space}{fn_arginfo},\n\ + \n{space}{fn_arginfo_macro}!{fn_arginfo_params},\n\ {}];\n", param_code.len() + 1, param_code.join(""), @@ -556,94 +627,75 @@ impl ArgInfoBuilder<'_> { func.by_ref, func.return_type.as_ref(), &doc_name, - )?; - self.parts.push(fn_result); + ); + self.parts.push(fn_result?); Ok(()) } /// Generate code for a class property. - #[expect(clippy::too_many_lines, reason = "It's a complicated function")] fn build_property(&mut self, prop: &PropertyDecl) -> Result { + self.scope.add_import("rsphp_sys", "zval"); + self.scope.add_import("rsphp_sys", "zend_class_entry"); let prop_name = prop.name.as_ref().ok_or("Property name missing")?; let prop_default_create = format!( "{space}let mut property_{name}_default_value: zval = unsafe {{ std::mem::zeroed() }};", name = prop_name, space = " " ); - let prop_default_init = match &prop.default { - None => format!( - "{space}unsafe {{ ZVAL_UNDEF!(std::ptr::from_mut::(&mut property_{name}_default_value)); }}", - name = prop_name, - space = " " - ), + // rsphp-macros-c macro to call, Option with an extra argument, and + // Option with extra code to put before the initialization + let (init_macro, init_arg, init_extra_code) = match &prop.default { + None => ("ZVAL_UNDEF", None, None), Some(Expr { kind: ExprKind::Null, span: _, - }) => format!( - "{space}unsafe {{ ZVAL_NULL!(std::ptr::from_mut::(&mut property_{name}_default_value)); }}", - name = prop_name, - space = " " - ), + }) => ("ZVAL_NULL", None, None), Some(Expr { kind: ExprKind::Bool(false), span: _, - }) => format!( - "{space}unsafe {{ ZVAL_FALSE!(std::ptr::from_mut::(&mut property_{name}_default_value)); }}", - name = prop_name, - space = " " - ), + }) => ("ZVAL_FALSE", None, None), Some(Expr { kind: ExprKind::Bool(true), span: _, - }) => format!( - "{space}unsafe {{ ZVAL_TRUE!(std::ptr::from_mut::(&mut property_{name}_default_value)); }}", - name = prop_name, - space = " " - ), + }) => ("ZVAL_TRUE", None, None), Some(Expr { kind: ExprKind::String(string), span: _, - }) if **string == *"" => format!( - "{space}unsafe {{ ZVAL_EMPTY_STRING!(std::ptr::from_mut::(&mut property_{name}_default_value)); }}", - name = prop_name, - space = " " - ), + }) if **string == *"" => ("ZVAL_EMPTY_STRING", None, None), Some(Expr { kind: ExprKind::Array(array), span: _, - }) if array.is_empty() => format!( - "{space}unsafe {{ ZVAL_EMPTY_ARRAY!(std::ptr::from_mut::(&mut property_{name}_default_value)); }}", - name = prop_name, - space = " " - ), + }) if array.is_empty() => ("ZVAL_EMPTY_ARRAY", None, None), Some(Expr { kind: ExprKind::Int(num), span: _, - }) => format!( - "{space}unsafe {{ ZVAL_LONG!(std::ptr::from_mut::(&mut property_{name}_default_value), {num}); }}", - name = prop_name, - space = " " - ), + }) => ("ZVAL_LONG", Some(num.to_string()), None), Some(Expr { kind: ExprKind::Identifier(ident), span: _, - }) if **ident == *"E_ERROR" => format!( - "{space}unsafe {{ ZVAL_LONG!(std::ptr::from_mut::(&mut property_{name}_default_value), E_ERROR); }}", - name = prop_name, - space = " " - ), + }) if **ident == *"E_ERROR" => { + self.scope.add_import("rsphp_sys", "E_ERROR"); + ("ZVAL_LONG", Some("E_ERROR".to_owned()), None) + } Some(Expr { kind: ExprKind::String(string), span: _, - }) => format!( - "{space}let property_{name}_default_str = unsafe {{ zend_string_init(c\"{s}\".as_ptr(), \"{s}\".len(), true) }};\ - \n{space}unsafe {{ ZVAL_INTERNED_STR!(std::ptr::from_mut::(&mut property_{name}_default_value), property_{name}_default_str); }}", - name = prop_name, - space = " ", - s = string, - ), + }) => { + self.scope.add_import("rsphp_sys", "zend_string_init"); + ( + "ZVAL_INTERNED_STR", + Some(format!("property_{prop_name}_default_str")), + Some(format!( + "{space}let property_{name}_default_str = unsafe {{ zend_string_init(c\"{s}\".as_ptr(), \"{s}\".len(), true) }};\n", + name = prop_name, + space = " ", + s = string + )), + ) + } _ => return Err(format!("Unhandled property default: {prop:?}")), }; + self.scope.add_import("rsphp_macros_c", init_macro); let prop_name_init = format!( "{space}let property_{name}_name: *mut zend_string = unsafe {{\ \n{space}{space}zend_string_init(\ @@ -655,24 +707,29 @@ impl ArgInfoBuilder<'_> { name = prop_name, space = " " ); + self.scope.add_import("rsphp_sys", "zend_string"); + self.scope.add_import("rsphp_sys", "zend_string_init"); let vis = match prop.visibility { None | Some(Visibility::Public) => "ZEND_ACC_PUBLIC", Some(Visibility::Protected) => "ZEND_ACC_PROTECTED", Some(Visibility::Private) => "ZEND_ACC_PRIVATE", }; + self.scope.add_import("rsphp_sys", vis); let (type_declaration, type_code) = match prop.type_hint.as_ref() { Some(type_hint) => { ArgInfoTypeRepr::try_from(type_hint.kind.clone(), self.namespace.as_ref())? - .property_type_code(self.namespace.as_ref(), prop_name)? + .property_type_code(&mut self.scope, self.namespace.as_ref(), prop_name)? } None => (None, "ZEND_TYPE_INIT_NONE!(0)".to_owned()), }; + let ptr_for_default = + format!("std::ptr::from_mut::(&mut property_{prop_name}_default_value)"); let prop_decl = format!( "{space}unsafe {{\ \n{space}{space}zend_declare_typed_property(\ \n{space}{space}{space}class_entry,\ \n{space}{space}{space}property_{name}_name,\ - \n{space}{space}{space}std::ptr::from_mut::(&mut property_{name}_default_value),\ + \n{space}{space}{space}{ptr_for_default},\ \n{space}{space}{space}{vis} as i32,\ \n{space}{space}{space}std::ptr::null_mut(),\ \n{space}{space}{space}{typemask},\ @@ -689,7 +746,21 @@ impl ArgInfoBuilder<'_> { name = prop_name, space = " " ); - let mut parts = vec![prop_default_create, prop_default_init, prop_name_init]; + self.scope + .add_import("rsphp_sys", "zend_declare_typed_property"); + self.scope.add_import("rsphp_sys", "zend_string_release"); + let mut parts = vec![prop_default_create]; + match init_extra_code { + None => (), + Some(code) => parts.push(code), + } + parts.push(format!( + "{space}unsafe {{ {init_macro}!({ptr_for_default}{sep}{extra_arg}); }}", + space = " ", + sep = if init_arg.is_some() { ", " } else { "" }, + extra_arg = init_arg.unwrap_or_default() + )); + parts.push(prop_name_init); match type_declaration { None => (), Some(code) => parts.push(code), @@ -700,7 +771,6 @@ impl ArgInfoBuilder<'_> { } /// Generate code for a class, enum, or interface declaration. - #[expect(clippy::too_many_lines, reason = "It's a complicated function")] fn class_like(&mut self, wrapped: &ClassLikeType) -> Result<(), String> { let class_name = wrapped.name(); let mut properties = vec![]; @@ -750,6 +820,7 @@ impl ArgInfoBuilder<'_> { )?); } method_verifications.push(verification); + self.needs_verification = true; } ClassLikeMember::Property(property) => { properties.push(self.build_property(&property)?); @@ -798,6 +869,7 @@ impl ArgInfoBuilder<'_> { registration_params.push(format!("{interface}: *mut zend_class_entry")); } if !method_verifications.is_empty() { + self.scope.add_import("rsphp_sys", "zend_function_entry"); registration_params.push("methods: &[zend_function_entry]".to_owned()); } // Registration function @@ -810,11 +882,8 @@ impl ArgInfoBuilder<'_> { .apply_to_methods(class_name, &method_verifications), }; let kind = wrapped.kind(); - let module_content = format!( - "use rsphp_macros_c::*;\n\ - {use_macros_rs}\ - use rsphp_sys::*;\n\ - {use_verify}\n\ + let mut module_content = format!( + "{use_verify}\n\ {module_parts}\n\ /// Register the `{doc_name}` {kind}.\ \npub(crate) fn register_{kind}({methods_param}) -> *mut zend_class_entry {{\ @@ -831,21 +900,41 @@ impl ArgInfoBuilder<'_> { methods_param = registration_params.join(", "), module_parts = module_parts.join("\n"), init_and_register_code = wrapped.init_and_register_code( + &mut self.scope, self.namespace.as_ref(), method_verifications.len(), self.program )?, space = " ", - use_macros_rs = if method_verifications.is_empty() { - "" - } else { - "use rsphp_macros_rs::*;\n" - }, use_verify = self.verification.apply_to_import( "use super::verify_registration;\n", method_verifications.is_empty() ), ); + // Some extra imports might be conditional + let flags_in_verification = VerificationData::get_all_flags(&method_verifications); + match self.verification { + VerificationMode::Never => (), + VerificationMode::Always => + { + #[expect(clippy::iter_over_hash_type, reason = "Order does not matter")] + for flag in flags_in_verification { + self.scope.add_import("rsphp_sys", flag); + } + } + VerificationMode::DebugAssert => { + let extra_flags_in_verification = self + .scope + .excluding_existing_sys_imports(&flags_in_verification); + if let Some(extra_use) = + ImportsUsed::as_use_single(&extra_flags_in_verification, "rsphp_sys") + { + module_content = + format!("#[cfg(debug_assertions)]\n{extra_use}") + &module_content; + } + } + } + module_content = self.scope.as_uses() + &module_content; let module_content_indented = module_content .split('\n') .map(|line| { @@ -874,7 +963,7 @@ impl ArgInfoBuilder<'_> { /// Generate code for registering an attribute on a class method. fn build_method_attribute( - &self, + &mut self, name: &str, attrib: &Attribute, verification: &mut VerificationData, @@ -894,15 +983,16 @@ impl ArgInfoBuilder<'_> { return Err(format!("Argument name has multiple parts: {arg:?}")); } let arg_name = &arg_name_full.parts[0]; - let init = match arg_name.as_ref() { - "since" => format!( - "(*(*attrib).args.as_mut_ptr().add({index})).name = ZSTR_KNOWN!(_zend_known_string_id::ZEND_STR_SINCE);", - ), - "message" => format!( - "(*(*attrib).args.as_mut_ptr().add({index})).name = ZSTR_KNOWN!(_zend_known_string_id::ZEND_STR_MESSAGE);", - ), + let known_name = match arg_name.as_ref() { + "since" => "_zend_known_string_id::ZEND_STR_SINCE", + "message" => "_zend_known_string_id::ZEND_STR_MESSAGE", _ => return Err(format!("Unhandled attribute parameter name: {name}")), }; + self.scope.add_import("rsphp_sys", "_zend_known_string_id"); + let init = format!( + "(*(*attrib).args.as_mut_ptr().add({index})).name = ZSTR_KNOWN!({known_name});", + ); + self.scope.add_import("rsphp_macros_c", "ZSTR_KNOWN"); param_init.push(init); } match &arg @@ -916,10 +1006,13 @@ impl ArgInfoBuilder<'_> { "let arg_{index}_value = zend_string_init(c\"{string}\".as_ptr(), \ \"{string}\".len(), true);", ); + self.scope.add_import("rsphp_sys", "zend_string_init"); param_init.push(alloc); let param_use = format!( "ZVAL_STR!(std::ptr::from_mut::(&mut (*(*attrib).args.as_mut_ptr().add({index})).value), arg_{index}_value);", ); + self.scope.add_import("rsphp_sys", "zval"); + self.scope.add_import("rsphp_macros_c", "ZVAL_STR"); param_init.push(param_use); } _ => return Err(format!("Unhandled attribute value: {arg:#?}")), @@ -929,25 +1022,43 @@ impl ArgInfoBuilder<'_> { if attrib_name == "Deprecated" { verification.add_flag("ZEND_ACC_DEPRECATED"); } + #[expect(clippy::single_match_else, reason = "Clearer as a match")] let (name_alloc, name_use, name_free) = match attrib_name.as_str() { - "Deprecated" => ( - "\n assert_eq!(10, ZSTR_LEN!(ZSTR_KNOWN!(_zend_known_string_id::ZEND_STR_DEPRECATED_CAPITALIZED)));".to_owned(), - "ZSTR_KNOWN!(_zend_known_string_id::ZEND_STR_DEPRECATED_CAPITALIZED)".to_owned(), - String::new() - ), - _ => ( - format!( - "\n{space}{space}let attrib_name: *mut zend_string = (zend_string_init_interned.expect(\"zend_string_init_interned should be set\"))(\ - c\"{name}\".as_ptr(),\ - \"{name}\".len(),\ - true);", - space = " ", - name = attrib_name - ), - "attrib_name".to_owned(), - "\n zend_string_release_ex(attrib_name, true);".to_owned() - ), + "Deprecated" => { + self.scope.add_import("rsphp_macros_c", "ZSTR_LEN"); + self.scope.add_import("rsphp_macros_c", "ZSTR_KNOWN"); + self.scope.add_import("rsphp_sys", "_zend_known_string_id"); + ( + "\n assert_eq!(10, ZSTR_LEN!(ZSTR_KNOWN!(_zend_known_string_id::ZEND_STR_DEPRECATED_CAPITALIZED)));".to_owned(), + "ZSTR_KNOWN!(_zend_known_string_id::ZEND_STR_DEPRECATED_CAPITALIZED)".to_owned(), + String::new() + ) + } + _ => { + self.scope.add_import("rsphp_sys", "zend_string"); + self.scope + .add_import("rsphp_sys", "zend_string_init_interned"); + self.scope.add_import("rsphp_sys", "zend_string_release_ex"); + ( + format!( + "\n{space}{space}let attrib_name: *mut zend_string = (zend_string_init_interned.expect(\"zend_string_init_interned should be set\"))(\ + c\"{name}\".as_ptr(),\ + \"{name}\".len(),\ + true);", + space = " ", + name = attrib_name + ), + "attrib_name".to_owned(), + "\n zend_string_release_ex(attrib_name, true);".to_owned(), + ) + } }; + self.scope.add_import("rsphp_sys", "zend_function"); + self.scope.add_import("rsphp_sys", "zend_hash_str_find_ptr"); + self.scope.add_import("rsphp_sys", "HashTable"); + self.scope.add_import("rsphp_sys", "zend_attribute"); + self.scope + .add_import("rsphp_sys", "zend_add_function_attribute"); Ok(format!( "{space}unsafe {{\ \n{space}{space}let fn_ptr: *mut zend_function = zend_hash_str_find_ptr(\ @@ -974,7 +1085,7 @@ impl ArgInfoBuilder<'_> { } /// Generate code for registering a class constant. - fn build_constant(&self, constant: &ClassConstDecl) -> Result { + fn build_constant(&mut self, constant: &ClassConstDecl) -> Result { let constant_name = constant .name .as_ref() @@ -984,6 +1095,7 @@ impl ArgInfoBuilder<'_> { Some(Visibility::Protected) => "ZEND_ACC_PROTECTED", Some(Visibility::Private) => "ZEND_ACC_PRIVATE", }; + self.scope.add_import("rsphp_sys", vis); let type_repr = ArgInfoTypeRepr::try_from( constant.type_hint.as_ref().map_or_else( || { @@ -1007,11 +1119,20 @@ impl ArgInfoBuilder<'_> { )?, self.namespace.as_ref(), )?; - let (_type_declaration, type_code) = - type_repr.property_type_code(self.namespace.as_ref(), constant_name)?; + let (_type_declaration, type_code) = type_repr.property_type_code( + &mut self.scope, + self.namespace.as_ref(), + constant_name, + )?; let init_code = match &constant.value.kind { - ExprKind::Int(num) => format!("ZVAL_LONG!(&mut value, {num});"), - ExprKind::Null => "ZVAL_NULL!(&mut value);".to_owned(), + ExprKind::Int(num) => { + self.scope.add_import("rsphp_macros_c", "ZVAL_LONG"); + format!("ZVAL_LONG!(&mut value, {num});") + } + ExprKind::Null => { + self.scope.add_import("rsphp_macros_c", "ZVAL_NULL"); + "ZVAL_NULL!(&mut value);".to_owned() + } ExprKind::Identifier(ident) if *ident == "UNKNOWN".into() => { let cvalue_re = Regex::new(r"@cvalue (\S+)").map_err(|err| err.to_string())?; let mut cvalue_val = cvalue_re @@ -1028,17 +1149,24 @@ impl ArgInfoBuilder<'_> { .as_str() .to_owned(); // Might not be something defined in core - if !cvalue_val.starts_with("ZEND_") { + if cvalue_val.starts_with("ZEND_") || cvalue_val.starts_with("PHP_") { + self.scope.add_import("rsphp_sys", cvalue_val.clone()); + } else { cvalue_val = "crate::".to_owned() + &cvalue_val; } match type_repr { ArgInfoTypeRepr::Builtin(BuiltinType::Int) => { + self.scope.add_import("rsphp_macros_c", "ZVAL_LONG"); format!("ZVAL_LONG!(&mut value, {cvalue_val} as i64);") } ArgInfoTypeRepr::Builtin(BuiltinType::Float) => { + self.scope.add_import("rsphp_macros_c", "ZVAL_DOUBLE"); format!("ZVAL_DOUBLE!(&mut value, {cvalue_val} as f64);") } ArgInfoTypeRepr::Builtin(BuiltinType::String) => { + self.scope.add_import("rsphp_sys", "zend_string"); + self.scope.add_import("rsphp_sys", "zend_string_init"); + self.scope.add_import("rsphp_macros_c", "ZVAL_STR"); format!( "let value_str: *mut zend_string = zend_string_init(\ \n{space3}{cvalue_val}.as_ptr().cast::(),\ @@ -1058,6 +1186,13 @@ impl ArgInfoBuilder<'_> { } _ => return Err(format!("Unhandled constant initialization: {constant:#?}")), }; + self.scope.add_import("rsphp_sys", "zval"); + self.scope.add_import("rsphp_sys", "zend_string"); + self.scope + .add_import("rsphp_sys", "zend_string_init_interned"); + self.scope + .add_import("rsphp_sys", "zend_declare_typed_class_constant"); + self.scope.add_import("rsphp_sys", "zend_string_release_ex"); Ok(format!( "{space}unsafe {{\ \n{space}{space}let mut value: zval = std::mem::zeroed();\ @@ -1078,7 +1213,7 @@ impl ArgInfoBuilder<'_> { } /// Generate code for registering an attribute for the overall class/interface/enum. - fn class_attribute(&self, attrib: &Attribute) -> Result { + fn class_attribute(&mut self, attrib: &Attribute) -> Result { let attrib_name = attrib .name .parts @@ -1129,6 +1264,10 @@ impl ArgInfoBuilder<'_> { _ => Err(format!("Unhandled attribute constant: {flag}")), }) .collect::, _>>()?; + for flag in &flags { + self.scope.add_import("rsphp_sys", *flag); + } + self.scope.add_import("rsphp_macros_c", "ZVAL_LONG"); let init = format!( "ZVAL_LONG!(&mut (*attrib).args[{index}].value, {flags} as i64);", flags = flags.join("|") @@ -1138,6 +1277,13 @@ impl ArgInfoBuilder<'_> { return Err(format!("Unsupported class attribute: {attrib:?}")); } } + self.scope.add_import("rsphp_sys", "zend_string"); + self.scope + .add_import("rsphp_sys", "zend_string_init_interned"); + self.scope.add_import("rsphp_sys", "zend_attribute"); + self.scope + .add_import("rsphp_sys", "zend_add_class_attribute"); + self.scope.add_import("rsphp_sys", "zend_string_release_ex"); Ok(format!( "{space}unsafe {{\ \n{space}{space}let name: *mut zend_string = (zend_string_init_interned.expect(\"zend_string_init_interned should be set\"))(\ @@ -1174,8 +1320,15 @@ impl ArgInfoBuilder<'_> { )); } return match &value.kind { - ExprKind::String(string) => Ok(format!( - "{space}{{\ + ExprKind::String(string) => { + self.scope.add_import("rsphp_sys", "zval"); + self.scope.add_import("rsphp_sys", "zend_string"); + self.scope.add_import("rsphp_sys", "zend_string_init"); + self.scope + .add_import("rsphp_sys", "zend_enum_add_case_cstr"); + self.scope.add_import("rsphp_macros_c", "ZVAL_STR"); + Ok(format!( + "{space}{{\ \n{space3}let mut value: zval = std::mem::zeroed();\ \n{space3}let value_str: *mut zend_string = zend_string_init(\ \n{space3}{space}c\"{val}\".as_ptr(),\ @@ -1185,25 +1338,34 @@ impl ArgInfoBuilder<'_> { \n{space3}ZVAL_STR!(std::ptr::from_mut::(&mut value), value_str);\ \n{space3}zend_enum_add_case_cstr(class_entry, c\"{name}\".as_ptr(), std::ptr::from_mut::(&mut value));\ \n{space}{space}}}", - name = case_name, - val = string, - space = " ", - space3 = " ", - )), - ExprKind::Int(num) => Ok(format!( - "{space}{{\ + name = case_name, + val = string, + space = " ", + space3 = " ", + )) + } + ExprKind::Int(num) => { + self.scope.add_import("rsphp_sys", "zval"); + self.scope + .add_import("rsphp_sys", "zend_enum_add_case_cstr"); + self.scope.add_import("rsphp_macros_c", "ZVAL_LONG"); + Ok(format!( + "{space}{{\ \n{space3}let mut value: zval = std::mem::zeroed();\ \n{space3}ZVAL_LONG!(std::ptr::from_mut::(&mut value), {val});\ \n{space3}zend_enum_add_case_cstr(class_entry, c\"{name}\".as_ptr(), std::ptr::from_mut::(&mut value));\ \n{space}{space}}}", - name = case_name, - val = num, - space = " ", - space3 = " ", - )), + name = case_name, + val = num, + space = " ", + space3 = " ", + )) + } _ => Err(format!("Unhandled enum backing: {case:#?}")), }; } + self.scope + .add_import("rsphp_sys", "zend_enum_add_case_cstr"); Ok(format!( "{space}zend_enum_add_case_cstr(class_entry, c\"{name}\".as_ptr(), std::ptr::null_mut());", name = case_name, @@ -1212,10 +1374,40 @@ impl ArgInfoBuilder<'_> { } /// Combine all of the code parts into the arginfo file contents. - pub(crate) fn assemble(&self) -> String { + pub(crate) fn assemble(&mut self) -> String { + // Some extra imports might be conditional + let mut extra_uses_code = String::new(); + let verification_code = if self.needs_verification { + let verification_imports = VERIFICATION_RSPHP_SYS_IMPORTS; + match self.verification { + VerificationMode::Never => (), + VerificationMode::Always => { + for import in verification_imports { + self.scope.add_import("rsphp_sys", *import); + } + } + VerificationMode::DebugAssert => { + let extra_verification_imports = self.scope.excluding_existing_sys_imports( + &verification_imports + .iter() + .map(|import| (*import).to_owned()) + .collect::>(), + ); + if let Some(extra_use) = + ImportsUsed::as_use_single(&extra_verification_imports, "rsphp_sys") + { + extra_uses_code = format!("#[cfg(debug_assertions)]\n{extra_use}"); + } + } + } + self.verification.get_infra() + } else { + String::new() + }; format!( - "use rsphp_macros_c::*;\nuse rsphp_macros_rs::*;\nuse rsphp_sys::*;\n{}\n{}\n", - self.verification.get_infra(), + "{}{extra_uses_code}{}\n{}\n", + self.scope.as_uses(), + verification_code, self.parts.join("\n") ) } diff --git a/crates/stub-parser/src/imports.rs b/crates/stub-parser/src/imports.rs new file mode 100644 index 0000000..fc24b03 --- /dev/null +++ b/crates/stub-parser/src/imports.rs @@ -0,0 +1,86 @@ +use std::collections::HashSet; + +/// Tracker for what imports need to be added to a given scope. +#[derive(Default)] +pub(crate) struct ImportsUsed { + /// Imports needed from `rsphp_sys`. + sys: HashSet, + /// Imports needed from `rsphp_macros_c`. + macros_c: HashSet, + /// Imports needed from `rsphp_macros_rs`. + macros_rs: HashSet, +} + +impl ImportsUsed { + /// Create a new empty set of imports. + pub(crate) fn new() -> Self { + Self { + sys: HashSet::new(), + macros_c: HashSet::new(), + macros_rs: HashSet::new(), + } + } + + /// Add a new use. + #[expect( + clippy::panic, + reason = "Indicates a bug in the library, surfaced at build time" + )] + #[expect( + unused_results, + reason = "HashSet used to prevent duplication, just need to include the import" + )] + pub(crate) fn add_import(&mut self, module: &str, name: T) + where + T: Into, + { + match module { + "rsphp_sys" => self.sys.insert(name.into()), + "rsphp_macros_c" => self.macros_c.insert(name.into()), + "rsphp_macros_rs" => self.macros_rs.insert(name.into()), + _ => panic!("Invalid use for module {module}"), + }; + } + + /// Add a few more imports for `rsphp_sys`. + pub(crate) fn extend_sys_imports(&mut self, names: T) + where + T: IntoIterator, + { + self.sys.extend(names); + } + + /// Identify the imports in the provided `HashSet` that are *not* in + /// the current imports for `rsphp_sys`. + pub(crate) fn excluding_existing_sys_imports( + &self, + target: &HashSet, + ) -> HashSet { + target - &self.sys + } + + /// Format all imports. + pub(crate) fn as_uses(&self) -> String { + vec![ + Self::as_use_single(&self.macros_c, "rsphp_macros_c"), + Self::as_use_single(&self.macros_rs, "rsphp_macros_rs"), + Self::as_use_single(&self.sys, "rsphp_sys"), + ] + .into_iter() + .flatten() + .collect::() + } + + /// Format imports for a single module. + pub(crate) fn as_use_single(used: &HashSet, module: &str) -> Option { + if used.is_empty() { + return None; + } + let mut used_names: Vec = used.clone().into_iter().collect(); + if used_names.len() == 1 { + return Some(format!("use {module}::{};\n", used_names[0])); + } + used_names.sort(); + Some(format!("use {module}::{{{}}};\n", used_names.join(", "))) + } +} diff --git a/crates/stub-parser/src/lib.rs b/crates/stub-parser/src/lib.rs index 686c82e..6110234 100644 --- a/crates/stub-parser/src/lib.rs +++ b/crates/stub-parser/src/lib.rs @@ -14,6 +14,9 @@ pub use crate::errors::ErrorCode; mod builder; use crate::builder::ArgInfoBuilder; +/// Module for `ImportsUsed`. +mod imports; + /// Module for `ArgInfoTypeRepr`. mod types; diff --git a/crates/stub-parser/src/types.rs b/crates/stub-parser/src/types.rs index 6ba95a4..1aa27f2 100644 --- a/crates/stub-parser/src/types.rs +++ b/crates/stub-parser/src/types.rs @@ -1,6 +1,8 @@ use php_ast::ast::{BuiltinType, NameKind}; use php_ast::owned::{Name, TypeHintKind}; +use crate::imports::ImportsUsed; + /// Information for a typehint for a function or parameter. #[derive(Debug)] #[expect( @@ -12,8 +14,12 @@ pub(crate) struct FunctionTypehint { pub(crate) class_info: Option, /// Info for type masks. pub(crate) mask_info: Option, + /// `rsphp_sys` imports to include when using the type mask. + pub(crate) mask_uses: Vec, /// Info for return types. pub(crate) return_info: Option, + /// `rsphp_sys` imports to use when including the return information. + pub(crate) return_uses: Vec, /// Whether the type is nullable. pub(crate) is_nullable: bool, } @@ -80,6 +86,7 @@ impl ArgInfoTypeRepr { /// second is the string to actually use. pub(crate) fn property_type_code( &self, + scope: &mut ImportsUsed, namespace: Option<&String>, name_str: &str, ) -> Result<(Option, String), String> { @@ -88,48 +95,70 @@ impl ArgInfoTypeRepr { None => String::new(), }; match self { - ArgInfoTypeRepr::Builtin(_) => Ok(( - None, - format!("ZEND_TYPE_INIT_MASK!({})", self.type_info()?.1), - )), + ArgInfoTypeRepr::Builtin(_) => { + let type_info = self.type_info()?; + scope.add_import("rsphp_sys", type_info.1); + scope.add_import("rsphp_macros_c", "ZEND_TYPE_INIT_MASK"); + Ok((None, format!("ZEND_TYPE_INIT_MASK!({})", type_info.1))) + } ArgInfoTypeRepr::Nullable(inner) => match **inner { - ArgInfoTypeRepr::Builtin(_) => Ok(( - None, - format!("ZEND_TYPE_INIT_MASK!({}|MAY_BE_NULL)", inner.type_info()?.1), - )), - ArgInfoTypeRepr::Named(_) | ArgInfoTypeRepr::FullyQualifiedNamed(_) => Ok(( - inner.property_type_code(namespace, name_str)?.0, - format!("ZEND_TYPE_INIT_CLASS!(property_{name_str}_type, 0, MAY_BE_NULL)"), - )), + ArgInfoTypeRepr::Builtin(_) => { + let type_info = inner.type_info()?; + scope.add_import("rsphp_sys", type_info.1); + scope.add_import("rsphp_sys", "MAY_BE_NULL"); + scope.add_import("rsphp_macros_c", "ZEND_TYPE_INIT_MASK"); + Ok(( + None, + format!("ZEND_TYPE_INIT_MASK!({}|MAY_BE_NULL)", type_info.1), + )) + } + ArgInfoTypeRepr::Named(_) | ArgInfoTypeRepr::FullyQualifiedNamed(_) => { + scope.add_import("rsphp_sys", "MAY_BE_NULL"); + scope.add_import("rsphp_macros_c", "ZEND_TYPE_INIT_CLASS"); + Ok(( + inner.property_type_code(scope, namespace, name_str)?.0, + format!("ZEND_TYPE_INIT_CLASS!(property_{name_str}_type, 0, MAY_BE_NULL)"), + )) + } _ => Err(format!("Unhandled type code: {self:?}")), }, - ArgInfoTypeRepr::Named(raw_name) => Ok(( - Some(format!( - "{space}let property_{name_str}_type: *mut zend_string = unsafe {{\ - \n{space}{space}zend_string_init(\ - \n{space}{space}{space}c\"{name}\".as_ptr(),\ - \n{space}{space}{space}\"{name}\".len(),\ - \n{space}{space}{space}true,\ - \n{space}{space})\ - \n{space}}};", - name = format!("{namespace_prefix}{raw_name}"), - space = " " - )), - format!("ZEND_TYPE_INIT_CLASS!(property_{name_str}_type, 0, 0)"), - )), - ArgInfoTypeRepr::FullyQualifiedNamed(name) => Ok(( - Some(format!( - "{space}let property_{name_str}_type: *mut zend_string = unsafe {{\ - \n{space}{space}zend_string_init(\ - \n{space}{space}{space}c\"{name}\".as_ptr(),\ - \n{space}{space}{space}\"{name}\".len(),\ - \n{space}{space}{space}true,\ - \n{space}{space})\ - \n{space}}};", - space = " " - )), - format!("ZEND_TYPE_INIT_CLASS!(property_{name_str}_type, 0, 0)"), - )), + ArgInfoTypeRepr::Named(raw_name) => { + scope.add_import("rsphp_sys", "zend_string"); + scope.add_import("rsphp_sys", "zend_string_init"); + scope.add_import("rsphp_macros_c", "ZEND_TYPE_INIT_CLASS"); + Ok(( + Some(format!( + "{space}let property_{name_str}_type: *mut zend_string = unsafe {{\ + \n{space}{space}zend_string_init(\ + \n{space}{space}{space}c\"{name}\".as_ptr(),\ + \n{space}{space}{space}\"{name}\".len(),\ + \n{space}{space}{space}true,\ + \n{space}{space})\ + \n{space}}};", + name = format!("{namespace_prefix}{raw_name}"), + space = " " + )), + format!("ZEND_TYPE_INIT_CLASS!(property_{name_str}_type, 0, 0)"), + )) + } + ArgInfoTypeRepr::FullyQualifiedNamed(name) => { + scope.add_import("rsphp_sys", "zend_string"); + scope.add_import("rsphp_sys", "zend_string_init"); + scope.add_import("rsphp_macros_c", "ZEND_TYPE_INIT_CLASS"); + Ok(( + Some(format!( + "{space}let property_{name_str}_type: *mut zend_string = unsafe {{\ + \n{space}{space}zend_string_init(\ + \n{space}{space}{space}c\"{name}\".as_ptr(),\ + \n{space}{space}{space}\"{name}\".len(),\ + \n{space}{space}{space}true,\ + \n{space}{space})\ + \n{space}}};", + space = " " + )), + format!("ZEND_TYPE_INIT_CLASS!(property_{name_str}_type, 0, 0)"), + )) + } ArgInfoTypeRepr::Union(inner) => { if inner .iter() @@ -139,6 +168,10 @@ impl ArgInfoTypeRepr { .iter() .map(|inner_type| inner_type.type_info().map(|inner_info| inner_info.1)) .collect::>()?; + for inner_flag in &parts { + scope.add_import("rsphp_sys", *inner_flag); + } + scope.add_import("rsphp_macros_c", "ZEND_TYPE_INIT_MASK"); Ok((None, format!("ZEND_TYPE_INIT_MASK!({})", parts.join("|")))) } else { Err(format!("Unhandled union: {inner:?}")) @@ -161,12 +194,19 @@ impl ArgInfoTypeRepr { Some(ns) => format!("{ns}\\\\"), None => String::new(), }; + let mut mask_uses = vec![]; + let mut return_uses = vec![]; let (class_type, mask, for_info) = match without_null { - ArgInfoTypeRepr::Builtin(_) => ( - None, - Some(without_null.type_info()?.1.to_owned()), - Some(without_null.type_info()?.0.to_owned()), - ), + ArgInfoTypeRepr::Builtin(_) => { + let type_info = without_null.type_info()?; + mask_uses.push(type_info.1.to_owned()); + return_uses.push(type_info.0.to_owned()); + ( + None, + Some(type_info.1.to_owned()), + Some(type_info.0.to_owned()), + ) + } ArgInfoTypeRepr::Named(name) => (Some(format!("{namespace_prefix}{name}")), None, None), ArgInfoTypeRepr::FullyQualifiedNamed(name) => (Some(name.clone()), None, None), ArgInfoTypeRepr::Union(inner) => { @@ -178,28 +218,36 @@ impl ArgInfoTypeRepr { if inner_repr.iter().any(|repr| repr.is_nullable) { return Err(format!("Union {inner:#?} contains nullable types")); } - let mask_parts = inner_repr - .iter() - .filter_map(|repr| repr.mask_info.clone()) - .collect::>(); - let info_parts = inner_repr - .iter() - .filter_map(|repr| repr.return_info.clone()) - .collect::>(); - let name_parts = inner_repr - .iter() - .filter_map(|repr| repr.class_info.clone()) - .collect::>(); + let mut total_mask_parts = vec![]; + let mut total_info_parts = vec![]; + let mut total_name_parts = vec![]; + for inner_type in inner_repr { + if let Some(info) = inner_type.mask_info { + total_mask_parts.push(info); + } + if let Some(return_info) = inner_type.return_info { + total_info_parts.push(return_info); + } + if let Some(class_info) = inner_type.class_info { + total_name_parts.push(class_info); + } + mask_uses.extend(inner_type.mask_uses); + return_uses.extend(inner_type.return_uses); + } // Might only contain basic types - if name_parts.is_empty() { - (None, Some(mask_parts.join("|")), Some(info_parts.join("|"))) - } else if mask_parts.is_empty() { - (Some(name_parts.join("|")), None, None) + if total_name_parts.is_empty() { + ( + None, + Some(total_mask_parts.join("|")), + Some(total_info_parts.join("|")), + ) + } else if total_mask_parts.is_empty() { + (Some(total_name_parts.join("|")), None, None) } else { ( - Some(name_parts.join("|")), - Some(mask_parts.join("|")), - Some(info_parts.join("|")), + Some(total_name_parts.join("|")), + Some(total_mask_parts.join("|")), + Some(total_info_parts.join("|")), ) } } @@ -210,13 +258,15 @@ impl ArgInfoTypeRepr { Ok(FunctionTypehint { class_info: class_type, mask_info: mask, + mask_uses, return_info: for_info, + return_uses, is_nullable, }) } /// For builtin types, get the `IS_*` and `MAY_BE_*` flags. - pub(crate) fn type_info(&self) -> Result<(&str, &str), String> { + fn type_info(&self) -> Result<(&str, &str), String> { let ArgInfoTypeRepr::Builtin(php_type) = self else { return Err(format!("type_info() called for {self:#?}")); }; diff --git a/crates/stub-parser/src/verification.rs b/crates/stub-parser/src/verification.rs index 4e03e37..bf7a0f1 100644 --- a/crates/stub-parser/src/verification.rs +++ b/crates/stub-parser/src/verification.rs @@ -1,4 +1,5 @@ use php_ast::ast::Visibility; +use std::collections::HashSet; use std::fmt::Write as _; /// How should calls to `register_class_*` methods be verified for correctness? @@ -102,6 +103,16 @@ impl VerificationData { } } + /// Get all of the flags that any of the methods use, for adding `use` + /// statements. + pub(crate) fn get_all_flags(methods: &[VerificationData]) -> HashSet { + let mut result = HashSet::new(); + for method in methods { + result.extend(method.flags.clone()); + } + result + } + /// Add a `ZEND_ACC_*` flag based on the visibility to the expected flags. pub(crate) fn add_visibility(&mut self, vis: Option<&Visibility>) { let flag = match vis { @@ -136,6 +147,15 @@ impl VerificationData { } } +/// Imports needed for infrastructure, at a file level. +pub(crate) const VERIFICATION_RSPHP_SYS_IMPORTS: &[&str] = &[ + "zend_function_entry", + "zend_internal_arg_info", + "zend_string", + "zend_type", + "zend_type_list", +]; + /// Infrastructure for registration verification. const VERIFICATION_INFRASTRUCTURE: &[&str] = &[ "\nuse std::ffi::{c_char, CStr};", @@ -174,7 +194,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { return Some("Expected a pointer to be set in the actual type".to_owned()); } // Compare the values depending on the flags - if expected.type_mask & _ZEND_TYPE_LITERAL_NAME_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_LITERAL_NAME_BIT != 0 { // CString pointers let expected_name = unsafe { CStr::from_ptr(expected.ptr.cast::()) }; let actual_name = unsafe { CStr::from_ptr(actual.ptr.cast::()) }; @@ -183,7 +203,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { } return Some(format!("Expected literal name {expected_name:?}, found {actual_name:?}")); } - if expected.type_mask & _ZEND_TYPE_NAME_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_NAME_BIT != 0 { // zend_string pointers, compare them by comparing the lengths and values let expected_name: &zend_string = unsafe { expected.ptr.cast::().as_ref().expect("Valid pointer") }; let actual_name: &zend_string = unsafe { actual.ptr.cast::().as_ref().expect("Valid pointer") }; @@ -197,7 +217,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { } return Some(format!("Expected name {expected_slice:?}, found {actual_slice:?}")); } - if expected.type_mask & _ZEND_TYPE_LIST_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_LIST_BIT != 0 { // zend_type_list pointers let expected_list: &zend_type_list = unsafe { expected.ptr.cast::().as_ref().expect("Valid pointer") }; let acutal_list: &zend_type_list = unsafe { actual.ptr.cast::().as_ref().expect("Valid pointer") }; diff --git a/crates/stub-parser/tests/cases/attribute_registration.expected b/crates/stub-parser/tests/cases/attribute_registration.expected index dd18665..fdcd3a1 100644 --- a/crates/stub-parser/tests/cases/attribute_registration.expected +++ b/crates/stub-parser/tests/cases/attribute_registration.expected @@ -1,12 +1,9 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `CustomCastable` class. pub(crate) mod CustomCastable { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_c::ZVAL_LONG; + use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION; + use rsphp_sys::{ZEND_ATTRIBUTE_TARGET_CLASS, zend_add_class_attribute, zend_attribute, zend_class_entry, zend_function_entry, zend_internal_arg_info, zend_string, zend_string_init_interned, zend_string_release_ex}; /// Argument information for `CustomCastable::__construct()`. pub(crate) const ARGINFO___CONSTRUCT: [zend_internal_arg_info; 1] = [ @@ -18,9 +15,9 @@ pub(crate) mod CustomCastable { assert_eq!(2, methods.len(), "CustomCastable should have 1 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "CustomCastable", methods); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "CustomCastable", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, diff --git a/crates/stub-parser/tests/cases/backed_enum.expected b/crates/stub-parser/tests/cases/backed_enum.expected index 14762ab..5c45c8b 100644 --- a/crates/stub-parser/tests/cases/backed_enum.expected +++ b/crates/stub-parser/tests/cases/backed_enum.expected @@ -1,17 +1,14 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `Demo` enum. pub(crate) mod Demo { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_macros_c::ZVAL_STR; + use rsphp_sys::{IS_STRING, zend_class_entry, zend_enum_add_case_cstr, zend_string, zend_string_init, zval}; /// Register the `Demo` enum. pub(crate) fn register_enum() -> *mut zend_class_entry { let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_enum( + rsphp_sys::zend_register_internal_enum( c"Demo".as_ptr(), IS_STRING, std::ptr::null_mut(), diff --git a/crates/stub-parser/tests/cases/class_constant_unknown.expected b/crates/stub-parser/tests/cases/class_constant_unknown.expected index 36ff6cb..42d5b6b 100644 --- a/crates/stub-parser/tests/cases/class_constant_unknown.expected +++ b/crates/stub-parser/tests/cases/class_constant_unknown.expected @@ -1,19 +1,16 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `Demo` class. pub(crate) mod Demo { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_macros_c::{ZEND_TYPE_INIT_MASK, ZVAL_LONG}; + use rsphp_sys::{MAY_BE_LONG, ZEND_ACC_DEPRECATED, ZEND_ACC_PUBLIC, zend_class_entry, zend_declare_typed_class_constant, zend_string, zend_string_init_interned, zend_string_release_ex, zval}; /// Register the `Demo` class. pub(crate) fn register_class() -> *mut zend_class_entry { let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Demo", NULL); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Demo", NULL); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, diff --git a/crates/stub-parser/tests/cases/class_constants.expected b/crates/stub-parser/tests/cases/class_constants.expected index bce3c03..a3f3337 100644 --- a/crates/stub-parser/tests/cases/class_constants.expected +++ b/crates/stub-parser/tests/cases/class_constants.expected @@ -1,12 +1,9 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `CustomCastable` class. pub(crate) mod CustomCastable { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_c::{ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE, ZEND_TYPE_INIT_MASK, ZVAL_LONG, ZVAL_UNDEF}; + use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION; + use rsphp_sys::{IS_LONG, MAY_BE_LONG, ZEND_ACC_FINAL, ZEND_ACC_PRIVATE, ZEND_ACC_PUBLIC, zend_class_entry, zend_declare_typed_class_constant, zend_declare_typed_property, zend_function_entry, zend_internal_arg_info, zend_string, zend_string_init, zend_string_init_interned, zend_string_release, zend_string_release_ex, zval}; /// Argument information for `CustomCastable::__construct()`. pub(crate) const ARGINFO___CONSTRUCT: [zend_internal_arg_info; 2] = [ @@ -19,9 +16,9 @@ pub(crate) mod CustomCastable { assert_eq!(2, methods.len(), "CustomCastable should have 1 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "CustomCastable", methods); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "CustomCastable", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), ZEND_ACC_FINAL, @@ -111,16 +108,16 @@ pub(crate) mod CustomCastable { } /// Module for `ConstantValues` class. pub(crate) mod ConstantValues { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_macros_c::{ZEND_TYPE_INIT_MASK, ZVAL_DOUBLE, ZVAL_STR}; + use rsphp_sys::{MAY_BE_DOUBLE, MAY_BE_STRING, PHP_OS, ZEND_ACC_PUBLIC, ZEND_DEBUG, zend_class_entry, zend_declare_typed_class_constant, zend_string, zend_string_init, zend_string_init_interned, zend_string_release_ex, zval}; /// Register the `ConstantValues` class. pub(crate) fn register_class() -> *mut zend_class_entry { let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "ConstantValues", NULL); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "ConstantValues", NULL); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, @@ -144,8 +141,8 @@ pub(crate) mod ConstantValues { unsafe { let mut value: zval = std::mem::zeroed(); let value_str: *mut zend_string = zend_string_init( - crate::PHP_OS.as_ptr().cast::(), - std::ffi::CStr::from_ptr(crate::PHP_OS.as_ptr().cast::()).count_bytes(), + PHP_OS.as_ptr().cast::(), + std::ffi::CStr::from_ptr(PHP_OS.as_ptr().cast::()).count_bytes(), true); ZVAL_STR!(&mut value, value_str); let name: *mut zend_string = (zend_string_init_interned.expect("zend_string_init_interned should be set"))( @@ -164,16 +161,16 @@ pub(crate) mod ConstantValues { } /// Module for `ImplicitPublicConstant` class. pub(crate) mod ImplicitPublicConstant { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_macros_c::{ZEND_TYPE_INIT_MASK, ZVAL_LONG}; + use rsphp_sys::{MAY_BE_LONG, ZEND_ACC_PUBLIC, zend_class_entry, zend_declare_typed_class_constant, zend_string, zend_string_init_interned, zend_string_release_ex, zval}; /// Register the `ImplicitPublicConstant` class. pub(crate) fn register_class() -> *mut zend_class_entry { let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "ImplicitPublicConstant", NULL); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "ImplicitPublicConstant", NULL); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, diff --git a/crates/stub-parser/tests/cases/class_extends.expected b/crates/stub-parser/tests/cases/class_extends.expected index 6ecb1af..9c18e02 100644 --- a/crates/stub-parser/tests/cases/class_extends.expected +++ b/crates/stub-parser/tests/cases/class_extends.expected @@ -1,19 +1,15 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `Base` class. pub(crate) mod Base { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_sys::zend_class_entry; /// Register the `Base` class. pub(crate) fn register_class() -> *mut zend_class_entry { let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Base", NULL); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Base", NULL); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, @@ -26,16 +22,15 @@ pub(crate) mod Base { } /// Module for `Demo` class. pub(crate) mod Demo { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_sys::zend_class_entry; /// Register the `Demo` class. pub(crate) fn register_class(zend_ce_Base: *mut zend_class_entry) -> *mut zend_class_entry { let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Demo", NULL); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Demo", NULL); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), zend_ce_Base, 0, diff --git a/crates/stub-parser/tests/cases/class_flags.expected b/crates/stub-parser/tests/cases/class_flags.expected index 263c7e6..9adf97b 100644 --- a/crates/stub-parser/tests/cases/class_flags.expected +++ b/crates/stub-parser/tests/cases/class_flags.expected @@ -1,19 +1,15 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `Demo` class. pub(crate) mod Demo { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_sys::{ZEND_ACC_FINAL, ZEND_ACC_NO_DYNAMIC_PROPERTIES, zend_class_entry}; /// Register the `Demo` class. pub(crate) fn register_class() -> *mut zend_class_entry { let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Demo", NULL); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Demo", NULL); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES, @@ -26,16 +22,15 @@ pub(crate) mod Demo { } /// Module for `Demo2` class. pub(crate) mod Demo2 { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_sys::{ZEND_ACC_FINAL, ZEND_ACC_NOT_SERIALIZABLE, zend_class_entry}; /// Register the `Demo2` class. pub(crate) fn register_class() -> *mut zend_class_entry { let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Demo2", NULL); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Demo2", NULL); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), ZEND_ACC_FINAL|ZEND_ACC_NOT_SERIALIZABLE, @@ -48,16 +43,15 @@ pub(crate) mod Demo2 { } /// Module for `Demo3` class. pub(crate) mod Demo3 { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_sys::{ZEND_ACC_FINAL, ZEND_ACC_NOT_SERIALIZABLE, ZEND_ACC_NO_DYNAMIC_PROPERTIES, zend_class_entry}; /// Register the `Demo3` class. pub(crate) fn register_class() -> *mut zend_class_entry { let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Demo3", NULL); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Demo3", NULL); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_NOT_SERIALIZABLE, diff --git a/crates/stub-parser/tests/cases/class_implements.expected b/crates/stub-parser/tests/cases/class_implements.expected index b33a551..5fa486b 100644 --- a/crates/stub-parser/tests/cases/class_implements.expected +++ b/crates/stub-parser/tests/cases/class_implements.expected @@ -1,19 +1,15 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `IDemo` interface. pub(crate) mod IDemo { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_sys::zend_class_entry; /// Register the `IDemo` interface. pub(crate) fn register_interface() -> *mut zend_class_entry { let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "IDemo", NULL); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "IDemo", NULL); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_interface( + rsphp_sys::zend_register_internal_interface( std::ptr::from_mut::(&mut ce), ) }; @@ -24,16 +20,15 @@ pub(crate) mod IDemo { } /// Module for `Demo` class. pub(crate) mod Demo { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_sys::{zend_class_entry, zend_class_implements}; /// Register the `Demo` class. pub(crate) fn register_class(zend_ce_IDemo: *mut zend_class_entry) -> *mut zend_class_entry { let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Demo", NULL); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Demo", NULL); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, diff --git a/crates/stub-parser/tests/cases/class_registration.expected b/crates/stub-parser/tests/cases/class_registration.expected index 42faa10..b480d32 100644 --- a/crates/stub-parser/tests/cases/class_registration.expected +++ b/crates/stub-parser/tests/cases/class_registration.expected @@ -1,19 +1,16 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `Demo` class. pub(crate) mod Demo { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_macros_c::{ZEND_TYPE_INIT_MASK, ZVAL_UNDEF}; + use rsphp_sys::{MAY_BE_LONG, ZEND_ACC_PRIVATE, zend_class_entry, zend_declare_typed_property, zend_string, zend_string_init, zend_string_release, zval}; /// Register the `Demo` class. pub(crate) fn register_class() -> *mut zend_class_entry { let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Demo", NULL); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Demo", NULL); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, diff --git a/crates/stub-parser/tests/cases/default_unknown_param.expected b/crates/stub-parser/tests/cases/default_unknown_param.expected index 71296cc..ba0f641 100644 --- a/crates/stub-parser/tests/cases/default_unknown_param.expected +++ b/crates/stub-parser/tests/cases/default_unknown_param.expected @@ -1,12 +1,9 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `Demo` class. pub(crate) mod Demo { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_c::ZEND_ARG_TYPE_INFO; + use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK; + use rsphp_sys::{IS_MIXED, MAY_BE_VOID, zend_class_entry, zend_function_entry, zend_internal_arg_info}; /// Argument information for `Demo::test1()`. pub(crate) const ARGINFO_TEST1: [zend_internal_arg_info; 2] = [ @@ -19,9 +16,9 @@ pub(crate) mod Demo { assert_eq!(2, methods.len(), "Demo should have 1 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Demo", methods); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Demo", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, diff --git a/crates/stub-parser/tests/cases/enum.expected b/crates/stub-parser/tests/cases/enum.expected index 7875851..a39359c 100644 --- a/crates/stub-parser/tests/cases/enum.expected +++ b/crates/stub-parser/tests/cases/enum.expected @@ -1,17 +1,13 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `CustomCasting\CastableTarget` enum. pub(crate) mod CustomCasting_CastableTarget { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_sys::{IS_UNDEF, zend_class_entry, zend_enum_add_case_cstr}; /// Register the `CustomCasting\CastableTarget` enum. pub(crate) fn register_enum() -> *mut zend_class_entry { let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_enum( + rsphp_sys::zend_register_internal_enum( c"CustomCasting\\CastableTarget".as_ptr(), IS_UNDEF, std::ptr::null_mut(), diff --git a/crates/stub-parser/tests/cases/enum_types.expected b/crates/stub-parser/tests/cases/enum_types.expected index d652b41..648b31a 100644 --- a/crates/stub-parser/tests/cases/enum_types.expected +++ b/crates/stub-parser/tests/cases/enum_types.expected @@ -1,17 +1,13 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `Unbacked` enum. pub(crate) mod Unbacked { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_sys::{IS_UNDEF, zend_class_entry, zend_enum_add_case_cstr}; /// Register the `Unbacked` enum. pub(crate) fn register_enum() -> *mut zend_class_entry { let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_enum( + rsphp_sys::zend_register_internal_enum( c"Unbacked".as_ptr(), IS_UNDEF, std::ptr::null_mut(), @@ -28,14 +24,14 @@ pub(crate) mod Unbacked { } /// Module for `IntBacked` enum. pub(crate) mod IntBacked { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_macros_c::ZVAL_LONG; + use rsphp_sys::{IS_LONG, zend_class_entry, zend_enum_add_case_cstr, zval}; /// Register the `IntBacked` enum. pub(crate) fn register_enum() -> *mut zend_class_entry { let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_enum( + rsphp_sys::zend_register_internal_enum( c"IntBacked".as_ptr(), IS_LONG, std::ptr::null_mut(), @@ -60,14 +56,14 @@ pub(crate) mod IntBacked { } /// Module for `StringBacked` enum. pub(crate) mod StringBacked { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_macros_c::ZVAL_STR; + use rsphp_sys::{IS_STRING, zend_class_entry, zend_enum_add_case_cstr, zend_string, zend_string_init, zval}; /// Register the `StringBacked` enum. pub(crate) fn register_enum() -> *mut zend_class_entry { let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_enum( + rsphp_sys::zend_register_internal_enum( c"StringBacked".as_ptr(), IS_STRING, std::ptr::null_mut(), diff --git a/crates/stub-parser/tests/cases/functions.expected b/crates/stub-parser/tests/cases/functions.expected index 3f0f265..ea660eb 100644 --- a/crates/stub-parser/tests/cases/functions.expected +++ b/crates/stub-parser/tests/cases/functions.expected @@ -1,6 +1,6 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; +use rsphp_macros_c::{ZEND_ARG_INFO, ZEND_ARG_INFO_WITH_DEFAULT_VALUE, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE}; +use rsphp_macros_rs::{ZEND_ARG_INFO_FOR_FUNCTION, ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK}; +use rsphp_sys::{IS_LONG, IS_STRING, MAY_BE_LONG, MAY_BE_STRING, MAY_BE_VOID, zend_internal_arg_info}; /// Argument information for `test1()`. pub(crate) const ARGINFO_TEST1: [zend_internal_arg_info; 1] = [ diff --git a/crates/stub-parser/tests/cases/interface_extends.expected b/crates/stub-parser/tests/cases/interface_extends.expected index 6558e09..5fe343f 100644 --- a/crates/stub-parser/tests/cases/interface_extends.expected +++ b/crates/stub-parser/tests/cases/interface_extends.expected @@ -1,19 +1,15 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `HasMagic` interface. pub(crate) mod HasMagic { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_sys::{zend_class_entry, zend_class_implements}; /// Register the `HasMagic` interface. pub(crate) fn register_interface(zend_ce_Countable: *mut zend_class_entry, zend_ce_Stringable: *mut zend_class_entry) -> *mut zend_class_entry { let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "HasMagic", NULL); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "HasMagic", NULL); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_interface( + rsphp_sys::zend_register_internal_interface( std::ptr::from_mut::(&mut ce), ) }; diff --git a/crates/stub-parser/tests/cases/interface_registration.expected b/crates/stub-parser/tests/cases/interface_registration.expected index ce5da48..65193dd 100644 --- a/crates/stub-parser/tests/cases/interface_registration.expected +++ b/crates/stub-parser/tests/cases/interface_registration.expected @@ -1,17 +1,13 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `CustomCasting\CastableTarget` enum. pub(crate) mod CustomCasting_CastableTarget { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_sys::{IS_UNDEF, zend_class_entry, zend_enum_add_case_cstr}; /// Register the `CustomCasting\CastableTarget` enum. pub(crate) fn register_enum() -> *mut zend_class_entry { let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_enum( + rsphp_sys::zend_register_internal_enum( c"CustomCasting\\CastableTarget".as_ptr(), IS_UNDEF, std::ptr::null_mut(), @@ -29,9 +25,9 @@ pub(crate) mod CustomCasting_CastableTarget { } /// Module for `CustomCasting\HasCustomCast` interface. pub(crate) mod CustomCasting_HasCustomCast { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_c::ZEND_ARG_OBJ_INFO; + use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION; + use rsphp_sys::{zend_class_entry, zend_function_entry, zend_internal_arg_info}; /// Argument information for `CustomCasting\HasCustomCast::__doCast()`. pub(crate) const ARGINFO___DOCAST: [zend_internal_arg_info; 2] = [ @@ -44,9 +40,9 @@ pub(crate) mod CustomCasting_HasCustomCast { assert_eq!(2, methods.len(), "CustomCasting\\HasCustomCast should have 1 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_NS_CLASS_ENTRY!(ce, "CustomCasting", "HasCustomCast", methods); + rsphp_macros_c::INIT_NS_CLASS_ENTRY!(ce, "CustomCasting", "HasCustomCast", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_interface( + rsphp_sys::zend_register_internal_interface( std::ptr::from_mut::(&mut ce), ) }; diff --git a/crates/stub-parser/tests/cases/method_attribs.expected b/crates/stub-parser/tests/cases/method_attribs.expected index 8fe6dfb..f3ce178 100644 --- a/crates/stub-parser/tests/cases/method_attribs.expected +++ b/crates/stub-parser/tests/cases/method_attribs.expected @@ -1,12 +1,9 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `Demo` class. pub(crate) mod Demo { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_c::{ZSTR_KNOWN, ZSTR_LEN, ZVAL_STR}; + use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK; + use rsphp_sys::{HashTable, MAY_BE_VOID, _zend_known_string_id, zend_add_function_attribute, zend_attribute, zend_class_entry, zend_function, zend_function_entry, zend_hash_str_find_ptr, zend_internal_arg_info, zend_string_init, zval}; /// Argument information for `Demo::test1()`. pub(crate) const ARGINFO_TEST1: [zend_internal_arg_info; 1] = [ @@ -18,9 +15,9 @@ pub(crate) mod Demo { assert_eq!(2, methods.len(), "Demo should have 1 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Demo", methods); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Demo", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, diff --git a/crates/stub-parser/tests/cases/methods.expected b/crates/stub-parser/tests/cases/methods.expected index e98a96c..1361f5f 100644 --- a/crates/stub-parser/tests/cases/methods.expected +++ b/crates/stub-parser/tests/cases/methods.expected @@ -1,12 +1,9 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `Demo` class. pub(crate) mod Demo { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_c::{ZEND_ARG_INFO, ZEND_ARG_INFO_WITH_DEFAULT_VALUE, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE}; + use rsphp_macros_rs::{ZEND_ARG_INFO_FOR_FUNCTION, ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK}; + use rsphp_sys::{IS_LONG, IS_STRING, MAY_BE_LONG, MAY_BE_STRING, MAY_BE_VOID, zend_class_entry, zend_function_entry, zend_internal_arg_info}; /// Argument information for `Demo::test1()`. pub(crate) const ARGINFO_TEST1: [zend_internal_arg_info; 1] = [ @@ -47,9 +44,9 @@ pub(crate) mod Demo { assert_eq!(7, methods.len(), "Demo should have 6 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Demo", methods); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Demo", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, diff --git a/crates/stub-parser/tests/cases/namespaced_bodies.expected b/crates/stub-parser/tests/cases/namespaced_bodies.expected index c28f209..654c5cb 100644 --- a/crates/stub-parser/tests/cases/namespaced_bodies.expected +++ b/crates/stub-parser/tests/cases/namespaced_bodies.expected @@ -1,12 +1,10 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; +use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK; +use rsphp_sys::{MAY_BE_ANY, MAY_BE_VOID, zend_internal_arg_info}; /// Module for `Demo\InDemoNamespace` class. pub(crate) mod Demo_InDemoNamespace { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION; + use rsphp_sys::{zend_class_entry, zend_function_entry, zend_internal_arg_info}; /// Argument information for `Demo\InDemoNamespace::__construct()`. pub(crate) const ARGINFO___CONSTRUCT: [zend_internal_arg_info; 1] = [ @@ -18,9 +16,9 @@ pub(crate) mod Demo_InDemoNamespace { assert_eq!(2, methods.len(), "Demo\\InDemoNamespace should have 1 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_NS_CLASS_ENTRY!(ce, "Demo", "InDemoNamespace", methods); + rsphp_macros_c::INIT_NS_CLASS_ENTRY!(ce, "Demo", "InDemoNamespace", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, @@ -38,9 +36,8 @@ pub(crate) const ARGINFO_DEMO_INDEMONAMESPACE: [zend_internal_arg_info; 1] = [ /// Module for `Other\InOtherNamespace` class. pub(crate) mod Other_InOtherNamespace { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION; + use rsphp_sys::{zend_class_entry, zend_function_entry, zend_internal_arg_info}; /// Argument information for `Other\InOtherNamespace::__construct()`. pub(crate) const ARGINFO___CONSTRUCT: [zend_internal_arg_info; 1] = [ @@ -52,9 +49,9 @@ pub(crate) mod Other_InOtherNamespace { assert_eq!(2, methods.len(), "Other\\InOtherNamespace should have 1 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_NS_CLASS_ENTRY!(ce, "Other", "InOtherNamespace", methods); + rsphp_macros_c::INIT_NS_CLASS_ENTRY!(ce, "Other", "InOtherNamespace", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, diff --git a/crates/stub-parser/tests/cases/namespaced_default.expected b/crates/stub-parser/tests/cases/namespaced_default.expected index f42c438..05f8356 100644 --- a/crates/stub-parser/tests/cases/namespaced_default.expected +++ b/crates/stub-parser/tests/cases/namespaced_default.expected @@ -1,12 +1,9 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `CustomCasting\CustomCastable` class. pub(crate) mod CustomCasting_CustomCastable { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_c::{ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE, ZEND_TYPE_INIT_MASK, ZVAL_LONG}; + use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION; + use rsphp_sys::{IS_LONG, MAY_BE_LONG, ZEND_ACC_FINAL, ZEND_ACC_PUBLIC, zend_class_entry, zend_declare_typed_class_constant, zend_function_entry, zend_internal_arg_info, zend_string, zend_string_init_interned, zend_string_release_ex, zval}; /// Argument information for `CustomCasting\CustomCastable::__construct()`. pub(crate) const ARGINFO___CONSTRUCT: [zend_internal_arg_info; 2] = [ @@ -19,9 +16,9 @@ pub(crate) mod CustomCasting_CustomCastable { assert_eq!(2, methods.len(), "CustomCasting\\CustomCastable should have 1 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_NS_CLASS_ENTRY!(ce, "CustomCasting", "CustomCastable", methods); + rsphp_macros_c::INIT_NS_CLASS_ENTRY!(ce, "CustomCasting", "CustomCastable", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), ZEND_ACC_FINAL, diff --git a/crates/stub-parser/tests/cases/namespaced_semi.expected b/crates/stub-parser/tests/cases/namespaced_semi.expected index 86c70e7..f789dbd 100644 --- a/crates/stub-parser/tests/cases/namespaced_semi.expected +++ b/crates/stub-parser/tests/cases/namespaced_semi.expected @@ -1,12 +1,10 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; +use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK; +use rsphp_sys::{MAY_BE_VOID, zend_internal_arg_info}; /// Module for `Demo\InDemoNamespace` class. pub(crate) mod Demo_InDemoNamespace { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION; + use rsphp_sys::{zend_class_entry, zend_function_entry, zend_internal_arg_info}; /// Argument information for `Demo\InDemoNamespace::__construct()`. pub(crate) const ARGINFO___CONSTRUCT: [zend_internal_arg_info; 1] = [ @@ -18,9 +16,9 @@ pub(crate) mod Demo_InDemoNamespace { assert_eq!(2, methods.len(), "Demo\\InDemoNamespace should have 1 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_NS_CLASS_ENTRY!(ce, "Demo", "InDemoNamespace", methods); + rsphp_macros_c::INIT_NS_CLASS_ENTRY!(ce, "Demo", "InDemoNamespace", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, diff --git a/crates/stub-parser/tests/cases/namespaced_types.expected b/crates/stub-parser/tests/cases/namespaced_types.expected index ce5da48..65193dd 100644 --- a/crates/stub-parser/tests/cases/namespaced_types.expected +++ b/crates/stub-parser/tests/cases/namespaced_types.expected @@ -1,17 +1,13 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `CustomCasting\CastableTarget` enum. pub(crate) mod CustomCasting_CastableTarget { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_sys::{IS_UNDEF, zend_class_entry, zend_enum_add_case_cstr}; /// Register the `CustomCasting\CastableTarget` enum. pub(crate) fn register_enum() -> *mut zend_class_entry { let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_enum( + rsphp_sys::zend_register_internal_enum( c"CustomCasting\\CastableTarget".as_ptr(), IS_UNDEF, std::ptr::null_mut(), @@ -29,9 +25,9 @@ pub(crate) mod CustomCasting_CastableTarget { } /// Module for `CustomCasting\HasCustomCast` interface. pub(crate) mod CustomCasting_HasCustomCast { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_c::ZEND_ARG_OBJ_INFO; + use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION; + use rsphp_sys::{zend_class_entry, zend_function_entry, zend_internal_arg_info}; /// Argument information for `CustomCasting\HasCustomCast::__doCast()`. pub(crate) const ARGINFO___DOCAST: [zend_internal_arg_info; 2] = [ @@ -44,9 +40,9 @@ pub(crate) mod CustomCasting_HasCustomCast { assert_eq!(2, methods.len(), "CustomCasting\\HasCustomCast should have 1 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_NS_CLASS_ENTRY!(ce, "CustomCasting", "HasCustomCast", methods); + rsphp_macros_c::INIT_NS_CLASS_ENTRY!(ce, "CustomCasting", "HasCustomCast", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_interface( + rsphp_sys::zend_register_internal_interface( std::ptr::from_mut::(&mut ce), ) }; diff --git a/crates/stub-parser/tests/cases/nullable_property.expected b/crates/stub-parser/tests/cases/nullable_property.expected index 2d36f6c..6d00bf1 100644 --- a/crates/stub-parser/tests/cases/nullable_property.expected +++ b/crates/stub-parser/tests/cases/nullable_property.expected @@ -1,19 +1,16 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `Reference` class. pub(crate) mod Reference { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_macros_c::{ZEND_TYPE_INIT_MASK, ZVAL_UNDEF}; + use rsphp_sys::{MAY_BE_NULL, MAY_BE_STRING, ZEND_ACC_FINAL, ZEND_ACC_NOT_SERIALIZABLE, ZEND_ACC_NO_DYNAMIC_PROPERTIES, ZEND_ACC_PUBLIC, zend_class_entry, zend_declare_typed_property, zend_string, zend_string_init, zend_string_release, zval}; /// Register the `Reference` class. pub(crate) fn register_class() -> *mut zend_class_entry { let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Reference", NULL); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Reference", NULL); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_NOT_SERIALIZABLE, diff --git a/crates/stub-parser/tests/cases/optional_object.expected b/crates/stub-parser/tests/cases/optional_object.expected index f6d7a8e..fd95279 100644 --- a/crates/stub-parser/tests/cases/optional_object.expected +++ b/crates/stub-parser/tests/cases/optional_object.expected @@ -1,12 +1,9 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `Repository` class. pub(crate) mod Repository { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_c::{ZEND_ARG_OBJ_INFO, ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE, ZEND_ARG_TYPE_INFO}; + use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_OBJ_INFO; + use rsphp_sys::{IS_ARRAY, IS_STRING, ZEND_ACC_FINAL, ZEND_ACC_NOT_SERIALIZABLE, ZEND_ACC_NO_DYNAMIC_PROPERTIES, zend_class_entry, zend_function_entry, zend_internal_arg_info}; /// Argument information for `Repository::commit()`. pub(crate) const ARGINFO_COMMIT: [zend_internal_arg_info; 6] = [ @@ -23,9 +20,9 @@ pub(crate) mod Repository { assert_eq!(2, methods.len(), "Repository should have 1 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Repository", methods); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Repository", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_NOT_SERIALIZABLE, @@ -38,16 +35,15 @@ pub(crate) mod Repository { } /// Module for `Oid` class. pub(crate) mod Oid { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_sys::{ZEND_ACC_FINAL, ZEND_ACC_NOT_SERIALIZABLE, ZEND_ACC_NO_DYNAMIC_PROPERTIES, zend_class_entry}; /// Register the `Oid` class. pub(crate) fn register_class() -> *mut zend_class_entry { let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Oid", NULL); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Oid", NULL); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_NOT_SERIALIZABLE, @@ -60,16 +56,15 @@ pub(crate) mod Oid { } /// Module for `Signature` class. pub(crate) mod Signature { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_sys::{ZEND_ACC_FINAL, ZEND_ACC_NOT_SERIALIZABLE, ZEND_ACC_NO_DYNAMIC_PROPERTIES, zend_class_entry}; /// Register the `Signature` class. pub(crate) fn register_class() -> *mut zend_class_entry { let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Signature", NULL); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Signature", NULL); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_NOT_SERIALIZABLE, diff --git a/crates/stub-parser/tests/cases/parameter_types.expected b/crates/stub-parser/tests/cases/parameter_types.expected index adabb0a..dd00c83 100644 --- a/crates/stub-parser/tests/cases/parameter_types.expected +++ b/crates/stub-parser/tests/cases/parameter_types.expected @@ -1,6 +1,6 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; +use rsphp_macros_c::{ZEND_ARG_INFO, ZEND_ARG_INFO_WITH_DEFAULT_VALUE, ZEND_ARG_OBJ_INFO, ZEND_ARG_OBJ_TYPE_MASK, ZEND_ARG_TYPE_MASK}; +use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK; +use rsphp_sys::{MAY_BE_BOOL, MAY_BE_LONG, MAY_BE_STRING, MAY_BE_VOID, zend_internal_arg_info}; /// Argument information for `noType()`. pub(crate) const ARGINFO_NOTYPE: [zend_internal_arg_info; 2] = [ diff --git a/crates/stub-parser/tests/cases/property_defaults.expected b/crates/stub-parser/tests/cases/property_defaults.expected index 3b45d23..3da76f9 100644 --- a/crates/stub-parser/tests/cases/property_defaults.expected +++ b/crates/stub-parser/tests/cases/property_defaults.expected @@ -1,19 +1,16 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `Demo` class. pub(crate) mod Demo { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_macros_c::{ZEND_TYPE_INIT_MASK, ZVAL_EMPTY_ARRAY, ZVAL_EMPTY_STRING, ZVAL_FALSE, ZVAL_INTERNED_STR, ZVAL_LONG, ZVAL_NULL, ZVAL_TRUE}; + use rsphp_sys::{MAY_BE_ANY, ZEND_ACC_PUBLIC, zend_class_entry, zend_declare_typed_property, zend_string, zend_string_init, zend_string_release, zval}; /// Register the `Demo` class. pub(crate) fn register_class() -> *mut zend_class_entry { let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Demo", NULL); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Demo", NULL); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, @@ -114,6 +111,7 @@ pub(crate) mod Demo { let mut property_str_other_default_value: zval = unsafe { std::mem::zeroed() }; let property_str_other_default_str = unsafe { zend_string_init(c"foo".as_ptr(), "foo".len(), true) }; + unsafe { ZVAL_INTERNED_STR!(std::ptr::from_mut::(&mut property_str_other_default_value), property_str_other_default_str); } let property_str_other_name: *mut zend_string = unsafe { zend_string_init( diff --git a/crates/stub-parser/tests/cases/tentative_return.expected b/crates/stub-parser/tests/cases/tentative_return.expected index 0984cdd..e8d3efc 100644 --- a/crates/stub-parser/tests/cases/tentative_return.expected +++ b/crates/stub-parser/tests/cases/tentative_return.expected @@ -1,12 +1,8 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `Demo` class. pub(crate) mod Demo { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_rs::{ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_OBJ_INFO, ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK}; + use rsphp_sys::{MAY_BE_ARRAY, MAY_BE_LONG, MAY_BE_STRING, zend_class_entry, zend_function_entry, zend_internal_arg_info}; /// Argument information for `Demo::test1()`. pub(crate) const ARGINFO_TEST1: [zend_internal_arg_info; 1] = [ @@ -28,9 +24,9 @@ pub(crate) mod Demo { assert_eq!(4, methods.len(), "Demo should have 3 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Demo", methods); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Demo", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, diff --git a/crates/stub-parser/tests/cases/typed_properties.expected b/crates/stub-parser/tests/cases/typed_properties.expected index 901fcf1..074968c 100644 --- a/crates/stub-parser/tests/cases/typed_properties.expected +++ b/crates/stub-parser/tests/cases/typed_properties.expected @@ -1,19 +1,16 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `RSGit\Commit` class. pub(crate) mod RSGit_Commit { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_macros_c::{ZEND_TYPE_INIT_CLASS, ZVAL_UNDEF}; + use rsphp_sys::{ZEND_ACC_FINAL, ZEND_ACC_NOT_SERIALIZABLE, ZEND_ACC_NO_DYNAMIC_PROPERTIES, ZEND_ACC_PUBLIC, zend_class_entry, zend_declare_typed_property, zend_string, zend_string_init, zend_string_release, zval}; /// Register the `RSGit\Commit` class. pub(crate) fn register_class() -> *mut zend_class_entry { let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_NS_CLASS_ENTRY!(ce, "RSGit", "Commit", NULL); + rsphp_macros_c::INIT_NS_CLASS_ENTRY!(ce, "RSGit", "Commit", NULL); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_NOT_SERIALIZABLE, @@ -115,9 +112,9 @@ pub(crate) mod RSGit_Commit { } /// Module for `RSGit\Oid` class. pub(crate) mod RSGit_Oid { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_c::{ZEND_TYPE_INIT_MASK, ZVAL_UNDEF}; + use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK; + use rsphp_sys::{MAY_BE_STRING, ZEND_ACC_FINAL, ZEND_ACC_NOT_SERIALIZABLE, ZEND_ACC_NO_DYNAMIC_PROPERTIES, ZEND_ACC_PUBLIC, zend_class_entry, zend_declare_typed_property, zend_function_entry, zend_internal_arg_info, zend_string, zend_string_init, zend_string_release, zval}; /// Argument information for `RSGit\Oid::__toString()`. pub(crate) const ARGINFO___TOSTRING: [zend_internal_arg_info; 1] = [ @@ -129,9 +126,9 @@ pub(crate) mod RSGit_Oid { assert_eq!(2, methods.len(), "RSGit\\Oid should have 1 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_NS_CLASS_ENTRY!(ce, "RSGit", "Oid", methods); + rsphp_macros_c::INIT_NS_CLASS_ENTRY!(ce, "RSGit", "Oid", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_NOT_SERIALIZABLE, @@ -166,16 +163,16 @@ pub(crate) mod RSGit_Oid { } /// Module for `RSGit\Signature` class. pub(crate) mod RSGit_Signature { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_macros_c::{ZEND_TYPE_INIT_CLASS, ZEND_TYPE_INIT_MASK, ZVAL_UNDEF}; + use rsphp_sys::{MAY_BE_STRING, ZEND_ACC_FINAL, ZEND_ACC_NOT_SERIALIZABLE, ZEND_ACC_NO_DYNAMIC_PROPERTIES, ZEND_ACC_PUBLIC, zend_class_entry, zend_declare_typed_property, zend_string, zend_string_init, zend_string_release, zval}; /// Register the `RSGit\Signature` class. pub(crate) fn register_class() -> *mut zend_class_entry { let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_NS_CLASS_ENTRY!(ce, "RSGit", "Signature", NULL); + rsphp_macros_c::INIT_NS_CLASS_ENTRY!(ce, "RSGit", "Signature", NULL); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_NOT_SERIALIZABLE, diff --git a/crates/stub-parser/tests/cases/variadic_param.expected b/crates/stub-parser/tests/cases/variadic_param.expected index 1e53512..26d00bb 100644 --- a/crates/stub-parser/tests/cases/variadic_param.expected +++ b/crates/stub-parser/tests/cases/variadic_param.expected @@ -1,12 +1,9 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; /// Module for `Demo` class. pub(crate) mod Demo { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_c::ZEND_ARG_VARIADIC_TYPE_INFO; + use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK; + use rsphp_sys::{IS_MIXED, MAY_BE_VOID, zend_class_entry, zend_function_entry, zend_internal_arg_info}; /// Argument information for `Demo::test1()`. pub(crate) const ARGINFO_TEST1: [zend_internal_arg_info; 2] = [ @@ -19,9 +16,9 @@ pub(crate) mod Demo { assert_eq!(2, methods.len(), "Demo should have 1 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Demo", methods); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Demo", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, diff --git a/crates/stub-parser/tests/compile_test.rs b/crates/stub-parser/tests/compile_test.rs index ba60fc3..ff26445 100644 --- a/crates/stub-parser/tests/compile_test.rs +++ b/crates/stub-parser/tests/compile_test.rs @@ -33,7 +33,7 @@ fn verify_directory(data_dir: &Path) -> Result<(), Box> { // There isn't a way to check that library code compiles, need to make // things into valid binary targets, i.e. with main functions let content_to_compile = - format!("#![allow(unused_imports, non_snake_case)]\n\n{content}\n\nfn main() {{}}"); + format!("#![allow(non_snake_case)]\n\n{content}\n\nfn main() {{}}"); let generated_content_file = tmp_dir.path().join(arginfo_name); fs::write(&generated_content_file, content_to_compile)?; } diff --git a/crates/stub-parser/tests/verification-cases/functions.expected b/crates/stub-parser/tests/verification-cases/functions.expected new file mode 100644 index 0000000..c29822b --- /dev/null +++ b/crates/stub-parser/tests/verification-cases/functions.expected @@ -0,0 +1,8 @@ +use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK; +use rsphp_sys::{MAY_BE_VOID, zend_internal_arg_info}; + +/// Argument information for `test1()`. +pub(crate) const ARGINFO_TEST1: [zend_internal_arg_info; 1] = [ + ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK!(0, 0, MAY_BE_VOID, 0), +]; + diff --git a/crates/stub-parser/tests/verification-cases/functions.stub.php b/crates/stub-parser/tests/verification-cases/functions.stub.php new file mode 100644 index 0000000..1b2f623 --- /dev/null +++ b/crates/stub-parser/tests/verification-cases/functions.stub.php @@ -0,0 +1,7 @@ + Option { return Some("Expected a pointer to be set in the actual type".to_owned()); } // Compare the values depending on the flags - if expected.type_mask & _ZEND_TYPE_LITERAL_NAME_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_LITERAL_NAME_BIT != 0 { // CString pointers let expected_name = unsafe { CStr::from_ptr(expected.ptr.cast::()) }; let actual_name = unsafe { CStr::from_ptr(actual.ptr.cast::()) }; @@ -49,7 +48,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { } return Some(format!("Expected literal name {expected_name:?}, found {actual_name:?}")); } - if expected.type_mask & _ZEND_TYPE_NAME_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_NAME_BIT != 0 { // zend_string pointers, compare them by comparing the lengths and values let expected_name: &zend_string = unsafe { expected.ptr.cast::().as_ref().expect("Valid pointer") }; let actual_name: &zend_string = unsafe { actual.ptr.cast::().as_ref().expect("Valid pointer") }; @@ -63,7 +62,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { } return Some(format!("Expected name {expected_slice:?}, found {actual_slice:?}")); } - if expected.type_mask & _ZEND_TYPE_LIST_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_LIST_BIT != 0 { // zend_type_list pointers let expected_list: &zend_type_list = unsafe { expected.ptr.cast::().as_ref().expect("Valid pointer") }; let acutal_list: &zend_type_list = unsafe { actual.ptr.cast::().as_ref().expect("Valid pointer") }; @@ -210,14 +209,13 @@ fn verify_registration( } /// Module for `CustomCasting\CastableTarget` enum. pub(crate) mod CustomCasting_CastableTarget { - use rsphp_macros_c::*; - use rsphp_sys::*; + use rsphp_sys::{IS_UNDEF, zend_class_entry, zend_enum_add_case_cstr}; /// Register the `CustomCasting\CastableTarget` enum. pub(crate) fn register_enum() -> *mut zend_class_entry { let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_enum( + rsphp_sys::zend_register_internal_enum( c"CustomCasting\\CastableTarget".as_ptr(), IS_UNDEF, std::ptr::null_mut(), @@ -235,9 +233,11 @@ pub(crate) mod CustomCasting_CastableTarget { } /// Module for `CustomCasting\HasCustomCast` interface. pub(crate) mod CustomCasting_HasCustomCast { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_c::ZEND_ARG_OBJ_INFO; + use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION; + use rsphp_sys::{zend_class_entry, zend_function_entry, zend_internal_arg_info}; + #[cfg(debug_assertions)] + use rsphp_sys::{ZEND_ACC_ABSTRACT, ZEND_ACC_PUBLIC}; #[cfg(debug_assertions)] use super::verify_registration; @@ -261,9 +261,9 @@ pub(crate) mod CustomCasting_HasCustomCast { assert_eq!(2, methods.len(), "CustomCasting\\HasCustomCast should have 1 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_NS_CLASS_ENTRY!(ce, "CustomCasting", "HasCustomCast", methods); + rsphp_macros_c::INIT_NS_CLASS_ENTRY!(ce, "CustomCasting", "HasCustomCast", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_interface( + rsphp_sys::zend_register_internal_interface( std::ptr::from_mut::(&mut ce), ) }; diff --git a/crates/stub-parser/tests/verification-cases/method_attribs.expected b/crates/stub-parser/tests/verification-cases/method_attribs.expected index 0ef122c..770ff65 100644 --- a/crates/stub-parser/tests/verification-cases/method_attribs.expected +++ b/crates/stub-parser/tests/verification-cases/method_attribs.expected @@ -1,6 +1,5 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; +#[cfg(debug_assertions)] +use rsphp_sys::{zend_function_entry, zend_internal_arg_info, zend_string, zend_type, zend_type_list}; #[cfg(debug_assertions)] use std::ffi::{c_char, CStr}; @@ -40,7 +39,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { return Some("Expected a pointer to be set in the actual type".to_owned()); } // Compare the values depending on the flags - if expected.type_mask & _ZEND_TYPE_LITERAL_NAME_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_LITERAL_NAME_BIT != 0 { // CString pointers let expected_name = unsafe { CStr::from_ptr(expected.ptr.cast::()) }; let actual_name = unsafe { CStr::from_ptr(actual.ptr.cast::()) }; @@ -49,7 +48,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { } return Some(format!("Expected literal name {expected_name:?}, found {actual_name:?}")); } - if expected.type_mask & _ZEND_TYPE_NAME_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_NAME_BIT != 0 { // zend_string pointers, compare them by comparing the lengths and values let expected_name: &zend_string = unsafe { expected.ptr.cast::().as_ref().expect("Valid pointer") }; let actual_name: &zend_string = unsafe { actual.ptr.cast::().as_ref().expect("Valid pointer") }; @@ -63,7 +62,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { } return Some(format!("Expected name {expected_slice:?}, found {actual_slice:?}")); } - if expected.type_mask & _ZEND_TYPE_LIST_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_LIST_BIT != 0 { // zend_type_list pointers let expected_list: &zend_type_list = unsafe { expected.ptr.cast::().as_ref().expect("Valid pointer") }; let acutal_list: &zend_type_list = unsafe { actual.ptr.cast::().as_ref().expect("Valid pointer") }; @@ -210,9 +209,11 @@ fn verify_registration( } /// Module for `Demo` class. pub(crate) mod Demo { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_c::{ZSTR_KNOWN, ZSTR_LEN, ZVAL_STR}; + use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK; + use rsphp_sys::{HashTable, MAY_BE_VOID, _zend_known_string_id, zend_add_function_attribute, zend_attribute, zend_class_entry, zend_function, zend_function_entry, zend_hash_str_find_ptr, zend_internal_arg_info, zend_string_init, zval}; + #[cfg(debug_assertions)] + use rsphp_sys::{ZEND_ACC_DEPRECATED, ZEND_ACC_PUBLIC}; #[cfg(debug_assertions)] use super::verify_registration; @@ -235,9 +236,9 @@ pub(crate) mod Demo { assert_eq!(2, methods.len(), "Demo should have 1 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Demo", methods); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Demo", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, diff --git a/crates/stub-parser/tests/verification-cases/methods.expected b/crates/stub-parser/tests/verification-cases/methods.expected index ac00339..c2130ff 100644 --- a/crates/stub-parser/tests/verification-cases/methods.expected +++ b/crates/stub-parser/tests/verification-cases/methods.expected @@ -1,6 +1,5 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; +#[cfg(debug_assertions)] +use rsphp_sys::{zend_function_entry, zend_internal_arg_info, zend_string, zend_type, zend_type_list}; #[cfg(debug_assertions)] use std::ffi::{c_char, CStr}; @@ -40,7 +39,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { return Some("Expected a pointer to be set in the actual type".to_owned()); } // Compare the values depending on the flags - if expected.type_mask & _ZEND_TYPE_LITERAL_NAME_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_LITERAL_NAME_BIT != 0 { // CString pointers let expected_name = unsafe { CStr::from_ptr(expected.ptr.cast::()) }; let actual_name = unsafe { CStr::from_ptr(actual.ptr.cast::()) }; @@ -49,7 +48,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { } return Some(format!("Expected literal name {expected_name:?}, found {actual_name:?}")); } - if expected.type_mask & _ZEND_TYPE_NAME_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_NAME_BIT != 0 { // zend_string pointers, compare them by comparing the lengths and values let expected_name: &zend_string = unsafe { expected.ptr.cast::().as_ref().expect("Valid pointer") }; let actual_name: &zend_string = unsafe { actual.ptr.cast::().as_ref().expect("Valid pointer") }; @@ -63,7 +62,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { } return Some(format!("Expected name {expected_slice:?}, found {actual_slice:?}")); } - if expected.type_mask & _ZEND_TYPE_LIST_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_LIST_BIT != 0 { // zend_type_list pointers let expected_list: &zend_type_list = unsafe { expected.ptr.cast::().as_ref().expect("Valid pointer") }; let acutal_list: &zend_type_list = unsafe { actual.ptr.cast::().as_ref().expect("Valid pointer") }; @@ -210,9 +209,10 @@ fn verify_registration( } /// Module for `Demo` class. pub(crate) mod Demo { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK; + use rsphp_sys::{MAY_BE_VOID, zend_class_entry, zend_function_entry, zend_internal_arg_info}; + #[cfg(debug_assertions)] + use rsphp_sys::{ZEND_ACC_PRIVATE, ZEND_ACC_PROTECTED, ZEND_ACC_PUBLIC, ZEND_ACC_STATIC}; #[cfg(debug_assertions)] use super::verify_registration; @@ -265,9 +265,9 @@ pub(crate) mod Demo { assert_eq!(7, methods.len(), "Demo should have 6 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "Demo", methods); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Demo", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, diff --git a/crates/stub-parser/tests/verification-cases/namespaced_semi.expected b/crates/stub-parser/tests/verification-cases/namespaced_semi.expected index 1eb37ea..7eeb67a 100644 --- a/crates/stub-parser/tests/verification-cases/namespaced_semi.expected +++ b/crates/stub-parser/tests/verification-cases/namespaced_semi.expected @@ -1,6 +1,7 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; +use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK; +use rsphp_sys::{MAY_BE_VOID, zend_internal_arg_info}; +#[cfg(debug_assertions)] +use rsphp_sys::{zend_function_entry, zend_string, zend_type, zend_type_list}; #[cfg(debug_assertions)] use std::ffi::{c_char, CStr}; @@ -40,7 +41,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { return Some("Expected a pointer to be set in the actual type".to_owned()); } // Compare the values depending on the flags - if expected.type_mask & _ZEND_TYPE_LITERAL_NAME_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_LITERAL_NAME_BIT != 0 { // CString pointers let expected_name = unsafe { CStr::from_ptr(expected.ptr.cast::()) }; let actual_name = unsafe { CStr::from_ptr(actual.ptr.cast::()) }; @@ -49,7 +50,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { } return Some(format!("Expected literal name {expected_name:?}, found {actual_name:?}")); } - if expected.type_mask & _ZEND_TYPE_NAME_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_NAME_BIT != 0 { // zend_string pointers, compare them by comparing the lengths and values let expected_name: &zend_string = unsafe { expected.ptr.cast::().as_ref().expect("Valid pointer") }; let actual_name: &zend_string = unsafe { actual.ptr.cast::().as_ref().expect("Valid pointer") }; @@ -63,7 +64,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { } return Some(format!("Expected name {expected_slice:?}, found {actual_slice:?}")); } - if expected.type_mask & _ZEND_TYPE_LIST_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_LIST_BIT != 0 { // zend_type_list pointers let expected_list: &zend_type_list = unsafe { expected.ptr.cast::().as_ref().expect("Valid pointer") }; let acutal_list: &zend_type_list = unsafe { actual.ptr.cast::().as_ref().expect("Valid pointer") }; @@ -210,9 +211,10 @@ fn verify_registration( } /// Module for `Demo\InDemoNamespace` class. pub(crate) mod Demo_InDemoNamespace { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION; + use rsphp_sys::{zend_class_entry, zend_function_entry, zend_internal_arg_info}; + #[cfg(debug_assertions)] + use rsphp_sys::ZEND_ACC_PUBLIC; #[cfg(debug_assertions)] use super::verify_registration; @@ -235,9 +237,9 @@ pub(crate) mod Demo_InDemoNamespace { assert_eq!(2, methods.len(), "Demo\\InDemoNamespace should have 1 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_NS_CLASS_ENTRY!(ce, "Demo", "InDemoNamespace", methods); + rsphp_macros_c::INIT_NS_CLASS_ENTRY!(ce, "Demo", "InDemoNamespace", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, diff --git a/crates/stub-parser/tests/verification-cases/no_methods.expected b/crates/stub-parser/tests/verification-cases/no_methods.expected new file mode 100644 index 0000000..2c3f968 --- /dev/null +++ b/crates/stub-parser/tests/verification-cases/no_methods.expected @@ -0,0 +1,110 @@ + +/// Module for `Example` class. +pub(crate) mod Example { + use rsphp_macros_c::{ZEND_TYPE_INIT_MASK, ZVAL_UNDEF}; + use rsphp_sys::{MAY_BE_STRING, ZEND_ACC_FINAL, ZEND_ACC_NOT_SERIALIZABLE, ZEND_ACC_NO_DYNAMIC_PROPERTIES, ZEND_ACC_PUBLIC, zend_class_entry, zend_declare_typed_property, zend_string, zend_string_init, zend_string_release, zval}; + + + /// Register the `Example` class. + pub(crate) fn register_class() -> *mut zend_class_entry { + let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Example", NULL); + let class_entry: *mut zend_class_entry = unsafe { + rsphp_sys::zend_register_internal_class_with_flags( + std::ptr::from_mut::(&mut ce), + std::ptr::null_mut(), + ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES|ZEND_ACC_NOT_SERIALIZABLE, + ) + }; + + let mut property_first_default_value: zval = unsafe { std::mem::zeroed() }; + unsafe { ZVAL_UNDEF!(std::ptr::from_mut::(&mut property_first_default_value)); } + let property_first_name: *mut zend_string = unsafe { + zend_string_init( + c"first".as_ptr(), + "first".len(), + true, + ) + }; + unsafe { + zend_declare_typed_property( + class_entry, + property_first_name, + std::ptr::from_mut::(&mut property_first_default_value), + ZEND_ACC_PUBLIC as i32, + std::ptr::null_mut(), + ZEND_TYPE_INIT_MASK!(MAY_BE_STRING), + ); + } + unsafe { + zend_string_release(property_first_name); + } + + let mut property_second_default_value: zval = unsafe { std::mem::zeroed() }; + unsafe { ZVAL_UNDEF!(std::ptr::from_mut::(&mut property_second_default_value)); } + let property_second_name: *mut zend_string = unsafe { + zend_string_init( + c"second".as_ptr(), + "second".len(), + true, + ) + }; + unsafe { + zend_declare_typed_property( + class_entry, + property_second_name, + std::ptr::from_mut::(&mut property_second_default_value), + ZEND_ACC_PUBLIC as i32, + std::ptr::null_mut(), + ZEND_TYPE_INIT_MASK!(MAY_BE_STRING), + ); + } + unsafe { + zend_string_release(property_second_name); + } + + class_entry + } +} +/// Module for `MyBoolean` enum. +pub(crate) mod MyBoolean { + use rsphp_sys::{IS_UNDEF, zend_class_entry, zend_enum_add_case_cstr}; + + + /// Register the `MyBoolean` enum. + pub(crate) fn register_enum() -> *mut zend_class_entry { + let class_entry: *mut zend_class_entry = unsafe { + rsphp_sys::zend_register_internal_enum( + c"MyBoolean".as_ptr(), + IS_UNDEF, + std::ptr::null_mut(), + ) + }; + unsafe { + zend_enum_add_case_cstr(class_entry, c"True".as_ptr(), std::ptr::null_mut()); + zend_enum_add_case_cstr(class_entry, c"False".as_ptr(), std::ptr::null_mut()); + }; + + + class_entry + } +} +/// Module for `Marker` interface. +pub(crate) mod Marker { + use rsphp_sys::zend_class_entry; + + + /// Register the `Marker` interface. + pub(crate) fn register_interface() -> *mut zend_class_entry { + let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "Marker", NULL); + let class_entry: *mut zend_class_entry = unsafe { + rsphp_sys::zend_register_internal_interface( + std::ptr::from_mut::(&mut ce), + ) + }; + + + class_entry + } +} diff --git a/crates/stub-parser/tests/verification-cases/no_methods.stub.php b/crates/stub-parser/tests/verification-cases/no_methods.stub.php new file mode 100644 index 0000000..50ba48d --- /dev/null +++ b/crates/stub-parser/tests/verification-cases/no_methods.stub.php @@ -0,0 +1,23 @@ + Option { return Some("Expected a pointer to be set in the actual type".to_owned()); } // Compare the values depending on the flags - if expected.type_mask & _ZEND_TYPE_LITERAL_NAME_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_LITERAL_NAME_BIT != 0 { // CString pointers let expected_name = unsafe { CStr::from_ptr(expected.ptr.cast::()) }; let actual_name = unsafe { CStr::from_ptr(actual.ptr.cast::()) }; @@ -49,7 +48,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { } return Some(format!("Expected literal name {expected_name:?}, found {actual_name:?}")); } - if expected.type_mask & _ZEND_TYPE_NAME_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_NAME_BIT != 0 { // zend_string pointers, compare them by comparing the lengths and values let expected_name: &zend_string = unsafe { expected.ptr.cast::().as_ref().expect("Valid pointer") }; let actual_name: &zend_string = unsafe { actual.ptr.cast::().as_ref().expect("Valid pointer") }; @@ -63,7 +62,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { } return Some(format!("Expected name {expected_slice:?}, found {actual_slice:?}")); } - if expected.type_mask & _ZEND_TYPE_LIST_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_LIST_BIT != 0 { // zend_type_list pointers let expected_list: &zend_type_list = unsafe { expected.ptr.cast::().as_ref().expect("Valid pointer") }; let acutal_list: &zend_type_list = unsafe { actual.ptr.cast::().as_ref().expect("Valid pointer") }; @@ -210,9 +209,10 @@ fn verify_registration( } /// Module for `IniDemo` class. pub(crate) mod IniDemo { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK; + use rsphp_sys::{MAY_BE_BOOL, MAY_BE_DOUBLE, MAY_BE_LONG, MAY_BE_STRING, zend_class_entry, zend_function_entry, zend_internal_arg_info}; + #[cfg(debug_assertions)] + use rsphp_sys::{ZEND_ACC_PUBLIC, ZEND_ACC_STATIC}; #[cfg(debug_assertions)] use super::verify_registration; @@ -259,9 +259,9 @@ pub(crate) mod IniDemo { assert_eq!(6, methods.len(), "IniDemo should have 5 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "IniDemo", methods); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "IniDemo", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, diff --git a/example/rust-ext-demo/src/lib.rs b/example/rust-ext-demo/src/lib.rs index 9cafb89..b388b34 100644 --- a/example/rust-ext-demo/src/lib.rs +++ b/example/rust-ext-demo/src/lib.rs @@ -29,34 +29,11 @@ mod ini_demo; use ini_demo::{class_ini_demo_methods, ini_demo_ptr}; #[rustfmt::skip] -#[cfg_attr( - not(test), - expect( - clippy::wildcard_imports, - reason = "rust-lang/rust-clippy#13186" - ) -)] #[expect(clippy::cast_possible_wrap)] mod rustdemo_arginfo; #[rustfmt::skip] -#[cfg_attr( - not(test), - expect( - clippy::wildcard_imports, - reason = "rust-lang/rust-clippy#13186" - ) -)] -#[expect(unused_imports)] mod opaquedata_arginfo; #[rustfmt::skip] -#[cfg_attr( - not(test), - expect( - clippy::wildcard_imports, - reason = "rust-lang/rust-clippy#13186" - ) -)] -#[expect(unused)] mod ini_demo_arginfo; extern "C" fn my_module_info(entry: *mut zend_module_entry) { diff --git a/example/rust-ext-demo/src/opaquedata_arginfo.rs b/example/rust-ext-demo/src/opaquedata_arginfo.rs index f39a763..a5fd63a 100644 --- a/example/rust-ext-demo/src/opaquedata_arginfo.rs +++ b/example/rust-ext-demo/src/opaquedata_arginfo.rs @@ -1,6 +1,5 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; +#[cfg(debug_assertions)] +use rsphp_sys::{zend_function_entry, zend_internal_arg_info, zend_string, zend_type, zend_type_list}; #[cfg(debug_assertions)] use std::ffi::{c_char, CStr}; @@ -40,7 +39,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { return Some("Expected a pointer to be set in the actual type".to_owned()); } // Compare the values depending on the flags - if expected.type_mask & _ZEND_TYPE_LITERAL_NAME_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_LITERAL_NAME_BIT != 0 { // CString pointers let expected_name = unsafe { CStr::from_ptr(expected.ptr.cast::()) }; let actual_name = unsafe { CStr::from_ptr(actual.ptr.cast::()) }; @@ -49,7 +48,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { } return Some(format!("Expected literal name {expected_name:?}, found {actual_name:?}")); } - if expected.type_mask & _ZEND_TYPE_NAME_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_NAME_BIT != 0 { // zend_string pointers, compare them by comparing the lengths and values let expected_name: &zend_string = unsafe { expected.ptr.cast::().as_ref().expect("Valid pointer") }; let actual_name: &zend_string = unsafe { actual.ptr.cast::().as_ref().expect("Valid pointer") }; @@ -63,7 +62,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { } return Some(format!("Expected name {expected_slice:?}, found {actual_slice:?}")); } - if expected.type_mask & _ZEND_TYPE_LIST_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_LIST_BIT != 0 { // zend_type_list pointers let expected_list: &zend_type_list = unsafe { expected.ptr.cast::().as_ref().expect("Valid pointer") }; let acutal_list: &zend_type_list = unsafe { actual.ptr.cast::().as_ref().expect("Valid pointer") }; @@ -210,9 +209,11 @@ fn verify_registration( } /// Module for `RustDemo\OpaqueData` class. pub(crate) mod RustDemo_OpaqueData { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_c::ZEND_ARG_TYPE_INFO; + use rsphp_macros_rs::{ZEND_ARG_INFO_FOR_FUNCTION, ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK}; + use rsphp_sys::{MAY_BE_BOOL, MAY_BE_VOID, _IS_BOOL, zend_class_entry, zend_function_entry, zend_internal_arg_info}; + #[cfg(debug_assertions)] + use rsphp_sys::ZEND_ACC_PUBLIC; #[cfg(debug_assertions)] use super::verify_registration; @@ -254,9 +255,9 @@ pub(crate) mod RustDemo_OpaqueData { assert_eq!(5, methods.len(), "RustDemo\\OpaqueData should have 4 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_NS_CLASS_ENTRY!(ce, "RustDemo", "OpaqueData", methods); + rsphp_macros_c::INIT_NS_CLASS_ENTRY!(ce, "RustDemo", "OpaqueData", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0, diff --git a/example/rust-ext-demo/src/rustdemo_arginfo.rs b/example/rust-ext-demo/src/rustdemo_arginfo.rs index 2f4bf73..c98f3e8 100644 --- a/example/rust-ext-demo/src/rustdemo_arginfo.rs +++ b/example/rust-ext-demo/src/rustdemo_arginfo.rs @@ -1,6 +1,8 @@ -use rsphp_macros_c::*; -use rsphp_macros_rs::*; -use rsphp_sys::*; +use rsphp_macros_c::{ZEND_ARG_INFO, ZEND_ARG_TYPE_INFO, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE, ZEND_ARG_VARIADIC_TYPE_INFO}; +use rsphp_macros_rs::ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK; +use rsphp_sys::{IS_DOUBLE, IS_LONG, IS_MIXED, IS_STRING, MAY_BE_STRING, MAY_BE_VOID, _IS_BOOL, zend_internal_arg_info}; +#[cfg(debug_assertions)] +use rsphp_sys::{zend_function_entry, zend_string, zend_type, zend_type_list}; #[cfg(debug_assertions)] use std::ffi::{c_char, CStr}; @@ -40,7 +42,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { return Some("Expected a pointer to be set in the actual type".to_owned()); } // Compare the values depending on the flags - if expected.type_mask & _ZEND_TYPE_LITERAL_NAME_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_LITERAL_NAME_BIT != 0 { // CString pointers let expected_name = unsafe { CStr::from_ptr(expected.ptr.cast::()) }; let actual_name = unsafe { CStr::from_ptr(actual.ptr.cast::()) }; @@ -49,7 +51,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { } return Some(format!("Expected literal name {expected_name:?}, found {actual_name:?}")); } - if expected.type_mask & _ZEND_TYPE_NAME_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_NAME_BIT != 0 { // zend_string pointers, compare them by comparing the lengths and values let expected_name: &zend_string = unsafe { expected.ptr.cast::().as_ref().expect("Valid pointer") }; let actual_name: &zend_string = unsafe { actual.ptr.cast::().as_ref().expect("Valid pointer") }; @@ -63,7 +65,7 @@ fn types_match(expected: &zend_type, actual: &zend_type) -> Option { } return Some(format!("Expected name {expected_slice:?}, found {actual_slice:?}")); } - if expected.type_mask & _ZEND_TYPE_LIST_BIT != 0 { + if expected.type_mask & rsphp_sys::_ZEND_TYPE_LIST_BIT != 0 { // zend_type_list pointers let expected_list: &zend_type_list = unsafe { expected.ptr.cast::().as_ref().expect("Valid pointer") }; let acutal_list: &zend_type_list = unsafe { actual.ptr.cast::().as_ref().expect("Valid pointer") }; @@ -266,9 +268,11 @@ pub(crate) const ARGINFO_DISPLAY_VALUE: [zend_internal_arg_info; 2] = [ /// Module for `RSDemo` class. pub(crate) mod RSDemo { - use rsphp_macros_c::*; - use rsphp_macros_rs::*; - use rsphp_sys::*; + use rsphp_macros_c::{ZEND_ARG_TYPE_INFO, ZEND_TYPE_INIT_MASK, ZVAL_UNDEF}; + use rsphp_macros_rs::{ZEND_ARG_INFO_FOR_FUNCTION, ZEND_ARG_INFO_FOR_FUNCTION_WITH_RETURN_TYPE_MASK}; + use rsphp_sys::{IS_LONG, MAY_BE_LONG, MAY_BE_STRING, MAY_BE_VOID, ZEND_ACC_PRIVATE, zend_class_entry, zend_declare_typed_property, zend_function_entry, zend_internal_arg_info, zend_string, zend_string_init, zend_string_release, zval}; + #[cfg(debug_assertions)] + use rsphp_sys::ZEND_ACC_PUBLIC; #[cfg(debug_assertions)] use super::verify_registration; @@ -304,9 +308,9 @@ pub(crate) mod RSDemo { assert_eq!(4, methods.len(), "RSDemo should have 3 methods"); let mut ce: zend_class_entry = unsafe { std::mem::zeroed() }; - INIT_CLASS_ENTRY!(ce, "RSDemo", methods); + rsphp_macros_c::INIT_CLASS_ENTRY!(ce, "RSDemo", methods); let class_entry: *mut zend_class_entry = unsafe { - zend_register_internal_class_with_flags( + rsphp_sys::zend_register_internal_class_with_flags( std::ptr::from_mut::(&mut ce), std::ptr::null_mut(), 0,