mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
Add support for final class constants
RFC: https://wiki.php.net/rfc/final_class_const Co-authored-by: Nikita Popov <nikita.ppv@gmail.com>
This commit is contained in:
parent
c6d4f60827
commit
a5360e80c2
@ -67,6 +67,8 @@ PHP 8.1 UPGRADE NOTES
|
||||
. Added support for intersection types.
|
||||
They cannot be combined with union types.
|
||||
RFC: https://wiki.php.net/rfc/pure-intersection-types
|
||||
. Added support for the final modifier for class constants.
|
||||
RFC: https://wiki.php.net/rfc/final_class_const
|
||||
|
||||
- Fileinfo:
|
||||
. The fileinfo functions now accept and return, respectively, finfo objects
|
||||
|
@ -23,5 +23,6 @@ class FooBar extends Foo implements ia {
|
||||
new FooBar;
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot inherit previously-inherited or override constant c from interface ia in %s on line %d
|
||||
===DONE===
|
||||
--EXPECT--
|
||||
===DONE===
|
||||
|
13
Zend/tests/constants/final_constants/final_const1.phpt
Normal file
13
Zend/tests/constants/final_constants/final_const1.phpt
Normal file
@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
Class constants support the final modifier
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class Foo
|
||||
{
|
||||
final const A = "foo";
|
||||
final public const B = "foo";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
22
Zend/tests/constants/final_constants/final_const10.phpt
Normal file
22
Zend/tests/constants/final_constants/final_const10.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Interface constants inherited from other interfaces can be redeclared
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
interface I1
|
||||
{
|
||||
const C = 1;
|
||||
}
|
||||
|
||||
interface I2
|
||||
{
|
||||
const C = 2;
|
||||
}
|
||||
|
||||
interface I3 extends I1, I2
|
||||
{
|
||||
const C = 3;
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
22
Zend/tests/constants/final_constants/final_const11.phpt
Normal file
22
Zend/tests/constants/final_constants/final_const11.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Class constants cannot be inherited from both a class and an interface
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class C
|
||||
{
|
||||
const C = 1;
|
||||
}
|
||||
|
||||
interface I
|
||||
{
|
||||
const C = 1;
|
||||
}
|
||||
|
||||
class C2 extends C implements I
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Class C2 inherits both C::C and I::C, which is ambiguous in %s on line %d
|
22
Zend/tests/constants/final_constants/final_const12.phpt
Normal file
22
Zend/tests/constants/final_constants/final_const12.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Interface constants cannot be inherited from other interfaces
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
interface I1
|
||||
{
|
||||
const C = 1;
|
||||
}
|
||||
|
||||
interface I2
|
||||
{
|
||||
const C = 2;
|
||||
}
|
||||
|
||||
interface I3 extends I1, I2
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Class I3 inherits both I1::C and I2::C, which is ambiguous in %s on line %d
|
18
Zend/tests/constants/final_constants/final_const2.phpt
Normal file
18
Zend/tests/constants/final_constants/final_const2.phpt
Normal file
@ -0,0 +1,18 @@
|
||||
--TEST--
|
||||
Final class constants cannot be overridden
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class Foo
|
||||
{
|
||||
final const A = "foo";
|
||||
}
|
||||
|
||||
class Bar extends Foo
|
||||
{
|
||||
const A = "bar";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Bar::A cannot override final constant Foo::A in %s on line %d
|
13
Zend/tests/constants/final_constants/final_const3.phpt
Normal file
13
Zend/tests/constants/final_constants/final_const3.phpt
Normal file
@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
Private class constants cannot be final
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class Foo
|
||||
{
|
||||
private final const A = "foo";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Private constant Foo::A cannot be final as it is not visible to other classes in %s on line %d
|
17
Zend/tests/constants/final_constants/final_const4.phpt
Normal file
17
Zend/tests/constants/final_constants/final_const4.phpt
Normal file
@ -0,0 +1,17 @@
|
||||
--TEST--
|
||||
Interface constants can be overridden directly
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
interface I
|
||||
{
|
||||
const X = 1;
|
||||
}
|
||||
|
||||
class C implements I
|
||||
{
|
||||
const X = 2;
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
18
Zend/tests/constants/final_constants/final_const5.phpt
Normal file
18
Zend/tests/constants/final_constants/final_const5.phpt
Normal file
@ -0,0 +1,18 @@
|
||||
--TEST--
|
||||
Final interface constants cannot be overridden directly
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
interface I
|
||||
{
|
||||
final public const X = 1;
|
||||
}
|
||||
|
||||
class C implements I
|
||||
{
|
||||
const X = 2;
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: C::X cannot override final constant I::X in %s on line %d
|
16
Zend/tests/constants/final_constants/final_const6.phpt
Normal file
16
Zend/tests/constants/final_constants/final_const6.phpt
Normal file
@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
Final interface constants can be inherited
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
interface I
|
||||
{
|
||||
final public const X = 1;
|
||||
}
|
||||
|
||||
class C implements I
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
19
Zend/tests/constants/final_constants/final_const7.phpt
Normal file
19
Zend/tests/constants/final_constants/final_const7.phpt
Normal file
@ -0,0 +1,19 @@
|
||||
--TEST--
|
||||
Interface constants can be overridden indirectly
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
interface I
|
||||
{
|
||||
const X = 1;
|
||||
}
|
||||
|
||||
class C implements I {}
|
||||
|
||||
class D extends C
|
||||
{
|
||||
const X = 2;
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
22
Zend/tests/constants/final_constants/final_const8.phpt
Normal file
22
Zend/tests/constants/final_constants/final_const8.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Class constants cannot be inherited from two different interfaces
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
interface I1
|
||||
{
|
||||
const C = 1;
|
||||
}
|
||||
|
||||
interface I2
|
||||
{
|
||||
const C = 1;
|
||||
}
|
||||
|
||||
class C implements I1, I2
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Class C inherits both I1::C and I2::C, which is ambiguous in %s on line %d
|
22
Zend/tests/constants/final_constants/final_const9.phpt
Normal file
22
Zend/tests/constants/final_constants/final_const9.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Class constants inherited from interfaces can be redeclared
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
interface I1
|
||||
{
|
||||
const C = 1;
|
||||
}
|
||||
|
||||
interface I2
|
||||
{
|
||||
const C = 2;
|
||||
}
|
||||
|
||||
class C implements I1, I2
|
||||
{
|
||||
const C = 3;
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
@ -17,4 +17,4 @@ class test implements test1, test2 {
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot inherit previously-inherited or override constant FOO from interface test2 in %s on line %d
|
||||
Fatal error: Class test inherits both test1::FOO and test2::FOO, which is ambiguous in %s on line %d
|
||||
|
@ -10,4 +10,4 @@ class test {
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot declare property test::$var final, the final modifier is allowed only for methods and classes in %s on line %d
|
||||
Fatal error: Cannot declare property test::$var final, the final modifier is allowed only for methods, classes, and class constants in %s on line %d
|
||||
|
@ -1,18 +0,0 @@
|
||||
--TEST--
|
||||
Inherited constant from interface
|
||||
--FILE--
|
||||
<?php
|
||||
interface foo {
|
||||
const foo = 'foobar';
|
||||
public function bar($x = foo);
|
||||
}
|
||||
|
||||
class foobar implements foo {
|
||||
const foo = 'bar';
|
||||
public function bar($x = foo::foo) {
|
||||
var_dump($x);
|
||||
}
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot inherit previously-inherited or override constant foo from interface foo in %s on line %d
|
@ -4331,12 +4331,12 @@ ZEND_API void zend_declare_property_stringl(zend_class_entry *ce, const char *na
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API zend_class_constant *zend_declare_class_constant_ex(zend_class_entry *ce, zend_string *name, zval *value, int access_type, zend_string *doc_comment) /* {{{ */
|
||||
ZEND_API zend_class_constant *zend_declare_class_constant_ex(zend_class_entry *ce, zend_string *name, zval *value, int flags, zend_string *doc_comment) /* {{{ */
|
||||
{
|
||||
zend_class_constant *c;
|
||||
|
||||
if (ce->ce_flags & ZEND_ACC_INTERFACE) {
|
||||
if (access_type != ZEND_ACC_PUBLIC) {
|
||||
if (!(flags & ZEND_ACC_PUBLIC)) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface constant %s::%s must be public", ZSTR_VAL(ce->name), ZSTR_VAL(name));
|
||||
}
|
||||
}
|
||||
@ -4356,7 +4356,7 @@ ZEND_API zend_class_constant *zend_declare_class_constant_ex(zend_class_entry *c
|
||||
c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
|
||||
}
|
||||
ZVAL_COPY_VALUE(&c->value, value);
|
||||
ZEND_CLASS_CONST_FLAGS(c) = access_type;
|
||||
ZEND_CLASS_CONST_FLAGS(c) = flags;
|
||||
c->doc_comment = doc_comment;
|
||||
c->attributes = NULL;
|
||||
c->ce = ce;
|
||||
|
@ -7270,7 +7270,7 @@ void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags, z
|
||||
|
||||
if (flags & ZEND_ACC_FINAL) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare property %s::$%s final, "
|
||||
"the final modifier is allowed only for methods and classes",
|
||||
"the final modifier is allowed only for methods, classes, and class constants",
|
||||
ZSTR_VAL(ce->name), ZSTR_VAL(name));
|
||||
}
|
||||
|
||||
@ -7358,10 +7358,17 @@ void zend_compile_class_const_decl(zend_ast *ast, uint32_t flags, zend_ast *attr
|
||||
zend_string *doc_comment = doc_comment_ast ? zend_string_copy(zend_ast_get_str(doc_comment_ast)) : NULL;
|
||||
zval value_zv;
|
||||
|
||||
if (UNEXPECTED(flags & (ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_FINAL))) {
|
||||
if (UNEXPECTED(flags & (ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT))) {
|
||||
zend_check_const_and_trait_alias_attr(flags, "constant");
|
||||
}
|
||||
|
||||
if (UNEXPECTED((flags & ZEND_ACC_PRIVATE) && (flags & ZEND_ACC_FINAL))) {
|
||||
zend_error_noreturn(
|
||||
E_COMPILE_ERROR, "Private constant %s::%s cannot be final as it is not visible to other classes",
|
||||
ZSTR_VAL(ce->name), ZSTR_VAL(name)
|
||||
);
|
||||
}
|
||||
|
||||
zend_const_expr_to_zval(&value_zv, value_ast_ptr);
|
||||
c = zend_declare_class_constant_ex(ce, name, &value_zv, flags, doc_comment);
|
||||
|
||||
|
@ -1337,6 +1337,13 @@ static void do_inherit_class_constant(zend_string *name, zend_class_constant *pa
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::%s must be %s (as in class %s)%s",
|
||||
ZSTR_VAL(ce->name), ZSTR_VAL(name), zend_visibility_string(ZEND_CLASS_CONST_FLAGS(parent_const)), ZSTR_VAL(parent_const->ce->name), (ZEND_CLASS_CONST_FLAGS(parent_const) & ZEND_ACC_PUBLIC) ? "" : " or weaker");
|
||||
}
|
||||
|
||||
if (UNEXPECTED((ZEND_CLASS_CONST_FLAGS(parent_const) & ZEND_ACC_FINAL))) {
|
||||
zend_error_noreturn(
|
||||
E_COMPILE_ERROR, "%s::%s cannot override final constant %s::%s",
|
||||
ZSTR_VAL(ce->name), ZSTR_VAL(name), ZSTR_VAL(parent_const->ce->name), ZSTR_VAL(name)
|
||||
);
|
||||
}
|
||||
} else if (!(ZEND_CLASS_CONST_FLAGS(parent_const) & ZEND_ACC_PRIVATE)) {
|
||||
if (Z_TYPE(parent_const->value) == IS_CONSTANT_AST) {
|
||||
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
|
||||
@ -1622,25 +1629,37 @@ ZEND_API void zend_do_inheritance_ex(zend_class_entry *ce, zend_class_entry *par
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static bool do_inherit_constant_check(HashTable *child_constants_table, zend_class_constant *parent_constant, zend_string *name, const zend_class_entry *iface) /* {{{ */
|
||||
{
|
||||
zval *zv = zend_hash_find_ex(child_constants_table, name, 1);
|
||||
zend_class_constant *old_constant;
|
||||
|
||||
if (zv != NULL) {
|
||||
old_constant = (zend_class_constant*)Z_PTR_P(zv);
|
||||
if (old_constant->ce != parent_constant->ce) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot inherit previously-inherited or override constant %s from interface %s", ZSTR_VAL(name), ZSTR_VAL(iface->name));
|
||||
}
|
||||
return 0;
|
||||
static bool do_inherit_constant_check(
|
||||
zend_class_entry *ce, zend_class_constant *parent_constant, zend_string *name
|
||||
) {
|
||||
zval *zv = zend_hash_find_ex(&ce->constants_table, name, 1);
|
||||
if (zv == NULL) {
|
||||
return true;
|
||||
}
|
||||
return 1;
|
||||
|
||||
zend_class_constant *old_constant = Z_PTR_P(zv);
|
||||
if ((ZEND_CLASS_CONST_FLAGS(parent_constant) & ZEND_ACC_FINAL)) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "%s::%s cannot override final constant %s::%s",
|
||||
ZSTR_VAL(old_constant->ce->name), ZSTR_VAL(name),
|
||||
ZSTR_VAL(parent_constant->ce->name), ZSTR_VAL(name)
|
||||
);
|
||||
}
|
||||
|
||||
if (old_constant->ce != parent_constant->ce && old_constant->ce != ce) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR,
|
||||
"Class %s inherits both %s::%s and %s::%s, which is ambiguous",
|
||||
ZSTR_VAL(ce->name),
|
||||
ZSTR_VAL(old_constant->ce->name), ZSTR_VAL(name),
|
||||
ZSTR_VAL(parent_constant->ce->name), ZSTR_VAL(name));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void do_inherit_iface_constant(zend_string *name, zend_class_constant *c, zend_class_entry *ce, zend_class_entry *iface) /* {{{ */
|
||||
{
|
||||
if (do_inherit_constant_check(&ce->constants_table, c, name, iface)) {
|
||||
if (do_inherit_constant_check(ce, c, name)) {
|
||||
zend_class_constant *ct;
|
||||
if (Z_TYPE(c->value) == IS_CONSTANT_AST) {
|
||||
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
|
||||
@ -1706,8 +1725,8 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry
|
||||
}
|
||||
if (ignore) {
|
||||
/* Check for attempt to redeclare interface constants */
|
||||
ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
|
||||
do_inherit_constant_check(&iface->constants_table, c, key, iface);
|
||||
ZEND_HASH_FOREACH_STR_KEY_PTR(&iface->constants_table, key, c) {
|
||||
do_inherit_constant_check(ce, c, key);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
} else {
|
||||
if (ce->num_interfaces >= current_iface_num) {
|
||||
@ -1751,8 +1770,8 @@ static void zend_do_implement_interfaces(zend_class_entry *ce, zend_class_entry
|
||||
return;
|
||||
}
|
||||
/* skip duplications */
|
||||
ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
|
||||
do_inherit_constant_check(&iface->constants_table, c, key, iface);
|
||||
ZEND_HASH_FOREACH_STR_KEY_PTR(&iface->constants_table, key, c) {
|
||||
do_inherit_constant_check(ce, c, key);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
iface = NULL;
|
||||
|
@ -565,9 +565,10 @@ static void _class_const_string(smart_str *str, char *name, zend_class_constant
|
||||
}
|
||||
|
||||
const char *visibility = zend_visibility_string(ZEND_CLASS_CONST_FLAGS(c));
|
||||
const char *final = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_FINAL ? "final " : "";
|
||||
const char *type = zend_zval_type_name(&c->value);
|
||||
smart_str_append_printf(str, "%sConstant [ %s %s %s ] { ",
|
||||
indent, visibility, type, name);
|
||||
smart_str_append_printf(str, "%sConstant [ %s%s %s %s ] { ",
|
||||
indent, final, visibility, type, name);
|
||||
if (Z_TYPE(c->value) == IS_ARRAY) {
|
||||
smart_str_appends(str, "Array");
|
||||
} else if (Z_TYPE(c->value) == IS_OBJECT) {
|
||||
@ -3831,18 +3832,25 @@ ZEND_METHOD(ReflectionClassConstant, isProtected)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* Returns whether this constant is final */
|
||||
ZEND_METHOD(ReflectionClassConstant, isFinal)
|
||||
{
|
||||
_class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_FINAL);
|
||||
}
|
||||
|
||||
/* {{{ Returns a bitfield of the access modifiers for this constant */
|
||||
ZEND_METHOD(ReflectionClassConstant, getModifiers)
|
||||
{
|
||||
reflection_object *intern;
|
||||
zend_class_constant *ref;
|
||||
uint32_t keep_flags = ZEND_ACC_FINAL | ZEND_ACC_PPP_MASK;
|
||||
|
||||
if (zend_parse_parameters_none() == FAILURE) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
GET_REFLECTION_OBJECT_PTR(ref);
|
||||
|
||||
RETURN_LONG(ZEND_CLASS_CONST_FLAGS(ref) & ZEND_ACC_PPP_MASK);
|
||||
RETURN_LONG(ZEND_CLASS_CONST_FLAGS(ref) & keep_flags);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -7102,6 +7110,7 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
|
||||
REGISTER_REFLECTION_CLASS_CONST_LONG(class_constant, "IS_PUBLIC", ZEND_ACC_PUBLIC);
|
||||
REGISTER_REFLECTION_CLASS_CONST_LONG(class_constant, "IS_PROTECTED", ZEND_ACC_PROTECTED);
|
||||
REGISTER_REFLECTION_CLASS_CONST_LONG(class_constant, "IS_PRIVATE", ZEND_ACC_PRIVATE);
|
||||
REGISTER_REFLECTION_CLASS_CONST_LONG(class_constant, "IS_FINAL", ZEND_ACC_FINAL);
|
||||
|
||||
reflection_extension_ptr = register_class_ReflectionExtension(reflector_ptr);
|
||||
reflection_init_class_handlers(reflection_extension_ptr);
|
||||
|
@ -475,6 +475,8 @@ class ReflectionClassConstant implements Reflector
|
||||
/** @tentative-return-type */
|
||||
public function isProtected(): bool {}
|
||||
|
||||
public function isFinal(): bool {}
|
||||
|
||||
/** @tentative-return-type */
|
||||
public function getModifiers(): int {}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: d8e686125cf213e019c1d706867e3c178fa057d2 */
|
||||
* Stub hash: 2564122a201ca462ee35ead1562c94da3ea3c8a3 */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 1, IS_ARRAY, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0)
|
||||
@ -396,6 +396,8 @@ ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_class_ReflectionClassConstant_isProtected arginfo_class_ReflectionFunctionAbstract_inNamespace
|
||||
|
||||
#define arginfo_class_ReflectionClassConstant_isFinal arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType
|
||||
|
||||
#define arginfo_class_ReflectionClassConstant_getModifiers arginfo_class_ReflectionFunctionAbstract_getNumberOfParameters
|
||||
|
||||
#define arginfo_class_ReflectionClassConstant_getDeclaringClass arginfo_class_ReflectionMethod_getDeclaringClass
|
||||
@ -736,6 +738,7 @@ ZEND_METHOD(ReflectionClassConstant, getValue);
|
||||
ZEND_METHOD(ReflectionClassConstant, isPublic);
|
||||
ZEND_METHOD(ReflectionClassConstant, isPrivate);
|
||||
ZEND_METHOD(ReflectionClassConstant, isProtected);
|
||||
ZEND_METHOD(ReflectionClassConstant, isFinal);
|
||||
ZEND_METHOD(ReflectionClassConstant, getModifiers);
|
||||
ZEND_METHOD(ReflectionClassConstant, getDeclaringClass);
|
||||
ZEND_METHOD(ReflectionClassConstant, getDocComment);
|
||||
@ -1015,6 +1018,7 @@ static const zend_function_entry class_ReflectionClassConstant_methods[] = {
|
||||
ZEND_ME(ReflectionClassConstant, isPublic, arginfo_class_ReflectionClassConstant_isPublic, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(ReflectionClassConstant, isPrivate, arginfo_class_ReflectionClassConstant_isPrivate, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(ReflectionClassConstant, isProtected, arginfo_class_ReflectionClassConstant_isProtected, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(ReflectionClassConstant, isFinal, arginfo_class_ReflectionClassConstant_isFinal, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(ReflectionClassConstant, getModifiers, arginfo_class_ReflectionClassConstant_getModifiers, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(ReflectionClassConstant, getDeclaringClass, arginfo_class_ReflectionClassConstant_getDeclaringClass, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(ReflectionClassConstant, getDocComment, arginfo_class_ReflectionClassConstant_getDocComment, ZEND_ACC_PUBLIC)
|
||||
|
@ -20,6 +20,8 @@ function reflectClassConstant($base, $constant) {
|
||||
var_dump($constInfo->isPrivate());
|
||||
echo "isProtected():\n";
|
||||
var_dump($constInfo->isProtected());
|
||||
echo "isFinal():\n";
|
||||
var_dump($constInfo->isFinal());
|
||||
echo "getModifiers():\n";
|
||||
var_dump($constInfo->getModifiers());
|
||||
echo "getDeclaringClass():\n";
|
||||
@ -34,12 +36,14 @@ class TestClass {
|
||||
/** Another doc comment */
|
||||
protected const PROT = 4;
|
||||
private const PRIV = "keepOut";
|
||||
public final const FINAL = "foo";
|
||||
}
|
||||
$instance = new TestClass();
|
||||
|
||||
reflectClassConstant("TestClass", "PUB");
|
||||
reflectClassConstant("TestClass", "PROT");
|
||||
reflectClassConstant("TestClass", "PRIV");
|
||||
reflectClassConstant("TestClass", "FINAL");
|
||||
reflectClassConstant($instance, "PRIV");
|
||||
reflectClassConstant($instance, "BAD_CONST");
|
||||
|
||||
@ -61,6 +65,8 @@ isPrivate():
|
||||
bool(false)
|
||||
isProtected():
|
||||
bool(false)
|
||||
isFinal():
|
||||
bool(false)
|
||||
getModifiers():
|
||||
int(1)
|
||||
getDeclaringClass():
|
||||
@ -88,6 +94,8 @@ isPrivate():
|
||||
bool(false)
|
||||
isProtected():
|
||||
bool(true)
|
||||
isFinal():
|
||||
bool(false)
|
||||
getModifiers():
|
||||
int(2)
|
||||
getDeclaringClass():
|
||||
@ -115,6 +123,8 @@ isPrivate():
|
||||
bool(true)
|
||||
isProtected():
|
||||
bool(false)
|
||||
isFinal():
|
||||
bool(false)
|
||||
getModifiers():
|
||||
int(4)
|
||||
getDeclaringClass():
|
||||
@ -125,6 +135,35 @@ object(ReflectionClass)#3 (1) {
|
||||
getDocComment():
|
||||
bool(false)
|
||||
|
||||
**********************************
|
||||
**********************************
|
||||
Reflecting on class constant TestClass::FINAL
|
||||
|
||||
__toString():
|
||||
string(47) "Constant [ final public string FINAL ] { foo }
|
||||
"
|
||||
getName():
|
||||
string(5) "FINAL"
|
||||
getValue():
|
||||
string(3) "foo"
|
||||
isPublic():
|
||||
bool(true)
|
||||
isPrivate():
|
||||
bool(false)
|
||||
isProtected():
|
||||
bool(false)
|
||||
isFinal():
|
||||
bool(true)
|
||||
getModifiers():
|
||||
int(33)
|
||||
getDeclaringClass():
|
||||
object(ReflectionClass)#3 (1) {
|
||||
["name"]=>
|
||||
string(9) "TestClass"
|
||||
}
|
||||
getDocComment():
|
||||
bool(false)
|
||||
|
||||
**********************************
|
||||
**********************************
|
||||
Reflecting on class constant TestClass::PRIV
|
||||
@ -142,6 +181,8 @@ isPrivate():
|
||||
bool(true)
|
||||
isProtected():
|
||||
bool(false)
|
||||
isFinal():
|
||||
bool(false)
|
||||
getModifiers():
|
||||
int(4)
|
||||
getDeclaringClass():
|
||||
|
@ -1,10 +0,0 @@
|
||||
--TEST--
|
||||
Final constants are not allowed
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
final const X = 1;
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot use 'final' as constant modifier in %s on line 3
|
@ -12,5 +12,5 @@ interface I2 extends I1 {
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot inherit previously-inherited or override constant FOO from interface I1 in %s on line 6
|
||||
--EXPECT--
|
||||
Done
|
||||
|
@ -1,16 +0,0 @@
|
||||
--TEST--
|
||||
Ensure a class may not shadow a constant inherited from an interface.
|
||||
--FILE--
|
||||
<?php
|
||||
interface I {
|
||||
const FOO = 10;
|
||||
}
|
||||
|
||||
class C implements I {
|
||||
const FOO = 10;
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot inherit previously-inherited or override constant FOO from interface I in %s on line 6
|
@ -1,19 +0,0 @@
|
||||
--TEST--
|
||||
Ensure a class may not inherit two constants with the same name from two separate interfaces.
|
||||
--FILE--
|
||||
<?php
|
||||
interface I1 {
|
||||
const FOO = 10;
|
||||
}
|
||||
|
||||
interface I2 {
|
||||
const FOO = 10;
|
||||
}
|
||||
|
||||
class C implements I1,I2 {
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot inherit previously-inherited or override constant FOO from interface I2 in %s on line 10
|
Loading…
Reference in New Issue
Block a user