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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
245 changes: 11 additions & 234 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,8 @@ c_str_macro = "1.0.3"
cc = "1.7.0"
clap = { version = "4.6.7", features = ["derive"] }
diff = "0.1.13"
php-ast = "0.21.0"
php-rs-parser = "0.21.0"
php-ast = "0.26.0"
php-rs-parser = "0.26.0"
proc-macro2 = "1.0.107"
regex = "1.13.1"
rsphp-build-tools = { version = "0.1.1", path = "./crates/build-tools" }
Expand Down
191 changes: 136 additions & 55 deletions crates/stub-parser/src/builder.rs

Large diffs are not rendered by default.

13 changes: 10 additions & 3 deletions crates/stub-parser/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ impl ArgInfoTypeRepr {
ArgInfoTypeRepr::FullyQualifiedNamed(ns.to_owned() + "\\" + &joined),
),
(NameKind::Error, _) => Err(format!("Type hint name error: {value:?}")),
(_, _) => Err(format!("NameKind is non-exhaustive, unhandled: {kind:?}")),
}
}
TypeHintKind::Nullable(inner) => Ok(ArgInfoTypeRepr::Nullable(Box::new(
Expand All @@ -79,6 +80,9 @@ impl ArgInfoTypeRepr {
TypeHintKind::Intersection(_) => {
Err("Intersection type hints not yet supported".to_owned())
}
_ => Err(format!(
"TypeHintKind is non-exhaustive, unhandled: {value:?}"
)),
}
}

Expand Down Expand Up @@ -271,10 +275,10 @@ impl ArgInfoTypeRepr {
return Err(format!("type_info() called for {self:#?}"));
};
match php_type {
BuiltinType::Int | BuiltinType::Integer => Ok(("IS_LONG", "MAY_BE_LONG")),
BuiltinType::Float | BuiltinType::Double => Ok(("IS_DOUBLE", "MAY_BE_DOUBLE")),
BuiltinType::Int => Ok(("IS_LONG", "MAY_BE_LONG")),
BuiltinType::Float => Ok(("IS_DOUBLE", "MAY_BE_DOUBLE")),
BuiltinType::String => Ok(("IS_STRING", "MAY_BE_STRING")),
BuiltinType::Bool | BuiltinType::Boolean => Ok(("_IS_BOOL", "MAY_BE_BOOL")),
BuiltinType::Bool => Ok(("_IS_BOOL", "MAY_BE_BOOL")),
BuiltinType::Void => Ok(("IS_VOID", "MAY_BE_VOID")),
BuiltinType::Never => Ok(("IS_NEVER", "MAY_BE_NEVER")),
BuiltinType::Mixed => Ok(("IS_MIXED", "MAY_BE_ANY")),
Expand All @@ -292,6 +296,9 @@ impl ArgInfoTypeRepr {
BuiltinType::Null => Ok(("IS_NULL", "MAY_BE_NULL")),
BuiltinType::True => Ok(("IS_TRUE", "MAY_BE_TRUE")),
BuiltinType::False => Ok(("IS_FALSE", "MAY_BE_FALSE")),
unknown => Err(format!(
"BuiltinType is non-exhaustive, unhandled: {unknown:?}"
)),
}
}
}
8 changes: 7 additions & 1 deletion crates/stub-parser/src/verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,19 @@ impl VerificationData {
}

/// Add a `ZEND_ACC_*` flag based on the visibility to the expected flags.
pub(crate) fn add_visibility(&mut self, vis: Option<&Visibility>) {
pub(crate) fn add_visibility(&mut self, vis: Option<&Visibility>) -> Result<(), String> {
let flag = match vis {
None | Some(Visibility::Public) => "ZEND_ACC_PUBLIC",
Some(Visibility::Protected) => "ZEND_ACC_PROTECTED",
Some(Visibility::Private) => "ZEND_ACC_PRIVATE",
Some(unknown) => {
return Err(format!(
"Visibility is non-exhaustive, unhandled: {unknown:?}"
));
}
};
self.add_flag(flag);
Ok(())
}

/// Add the specified flag to the expected flags.
Expand Down
3 changes: 3 additions & 0 deletions crates/stub-parser/tests/bundled_panic_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@ fn verify_walker(walker: WalkDir) -> Result<(), Box<dyn std::error::Error>> {
// php_date uses global constants to set the class constant
// php_sql.stub.php uses iterable
// zend_test splits the doc comment into two for one of the constants
// listformatter.stub.php uses #if conditions to specify the definition
// of IntlListFromatter::TYPE_AND and ::WIDTH_WIDE,
skip!(
"zend_builtin_functions",
"zend_constants",
"php_date",
"php_spl",
"test",
"listformatter",
);
let path = entry.into_path();
// We don't care about the actual result, just that .expect() does not
Expand Down
72 changes: 72 additions & 0 deletions crates/stub-parser/tests/cases/class_flags.expected
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,75 @@ pub(crate) mod Demo3 {
class_entry
}
}
/// Module for `IsAbstract` class.
pub(crate) mod IsAbstract {
use rsphp_sys::{ZEND_ACC_ABSTRACT, zend_class_entry};


/// Register the `IsAbstract` 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, "IsAbstract", NULL);
let class_entry: *mut zend_class_entry = unsafe {
rsphp_sys::zend_register_internal_class_with_flags(
std::ptr::from_mut::<zend_class_entry>(&mut ce),
std::ptr::null_mut(),
ZEND_ACC_ABSTRACT,
)
};


class_entry
}
}
/// Module for `IsReadOnly` class.
pub(crate) mod IsReadOnly {
use rsphp_sys::{ZEND_ACC_FINAL, ZEND_ACC_READONLY_CLASS, zend_class_entry};


/// Register the `IsReadOnly` 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, "IsReadOnly", NULL);
let class_entry: *mut zend_class_entry = unsafe {
rsphp_sys::zend_register_internal_class_with_flags(
std::ptr::from_mut::<zend_class_entry>(&mut ce),
std::ptr::null_mut(),
ZEND_ACC_FINAL|ZEND_ACC_READONLY_CLASS,
)
};


class_entry
}
}
/// Module for `AllowsDynamicProperties` class.
pub(crate) mod AllowsDynamicProperties {
use rsphp_sys::{ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES, zend_add_class_attribute, zend_class_entry, zend_string, zend_string_init_interned, zend_string_release_ex};


/// Register the `AllowsDynamicProperties` 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, "AllowsDynamicProperties", NULL);
let class_entry: *mut zend_class_entry = unsafe {
rsphp_sys::zend_register_internal_class_with_flags(
std::ptr::from_mut::<zend_class_entry>(&mut ce),
std::ptr::null_mut(),
ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES,
)
};


unsafe {
let name: *mut zend_string = (zend_string_init_interned.expect("zend_string_init_interned should be set"))(
c"AllowDynamicProperties".as_ptr(),
"AllowDynamicProperties".len(),
true,
);
zend_add_class_attribute(class_entry, name, 0);
zend_string_release_ex(name, true);
}
class_entry
}
}
9 changes: 8 additions & 1 deletion crates/stub-parser/tests/cases/class_flags.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,11 @@ final class Demo2 {}
* @strict-properties
* @not-serializable
*/
final class Demo3 {}
final class Demo3 {}

abstract class IsAbstract {}

final readonly class IsReadOnly {}

#[\AllowDynamicProperties]
class AllowsDynamicProperties {}
8 changes: 4 additions & 4 deletions crates/stub-parser/tests/cases/nullable_property.expected
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/// Module for `Reference` class.
pub(crate) mod Reference {
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};
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_ACC_READONLY, zend_class_entry, zend_declare_typed_property, zend_string, zend_string_init, zend_string_release, zval};


/// Register the `Reference` class.
Expand Down Expand Up @@ -31,7 +31,7 @@ pub(crate) mod Reference {
class_entry,
property_name_name,
std::ptr::from_mut::<zval>(&mut property_name_default_value),
ZEND_ACC_PUBLIC as i32,
(ZEND_ACC_PUBLIC|ZEND_ACC_READONLY) as i32,
std::ptr::null_mut(),
ZEND_TYPE_INIT_MASK!(MAY_BE_STRING),
);
Expand All @@ -54,7 +54,7 @@ pub(crate) mod Reference {
class_entry,
property_shorthand_name,
std::ptr::from_mut::<zval>(&mut property_shorthand_default_value),
ZEND_ACC_PUBLIC as i32,
(ZEND_ACC_PUBLIC|ZEND_ACC_READONLY) as i32,
std::ptr::null_mut(),
ZEND_TYPE_INIT_MASK!(MAY_BE_STRING),
);
Expand All @@ -77,7 +77,7 @@ pub(crate) mod Reference {
class_entry,
property_symbolicTarget_name,
std::ptr::from_mut::<zval>(&mut property_symbolicTarget_default_value),
ZEND_ACC_PUBLIC as i32,
(ZEND_ACC_PUBLIC|ZEND_ACC_READONLY) as i32,
std::ptr::null_mut(),
ZEND_TYPE_INIT_MASK!(MAY_BE_STRING|MAY_BE_NULL),
);
Expand Down
Loading
Loading