Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4233394

Browse files
ReflectionClass: show enums differently from classes
While internally enums are mostly the same as classes, their output in `ReflectionClass::__toString()` should show the enum as the developer wrote it, rather than as the engine stored it. Accordingly - Say that the enum is an enum, not a final class - Include the backing type, if any, in the declaration line - List enum cases separately from constants, and show the underlying values, if any GH-15766
1 parent 6c81f70 commit 4233394

6 files changed

+126
-39
lines changed

‎ext/reflection/php_reflection.c‎

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@ static void _const_string(smart_str *str, const char *name, zval *value, const c
306306
static void _function_string(smart_str *str, zend_function *fptr, zend_class_entry *scope, const char* indent);
307307
static void _property_string(smart_str *str, zend_property_info *prop, const char *prop_name, const char* indent);
308308
static void _class_const_string(smart_str *str, const zend_string *name, zend_class_constant *c, const char* indent);
309+
static void _enum_case_string(smart_str *str, const zend_string *name, zend_class_constant *c, const char* indent);
309310
static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, const char *indent);
310311
static void _extension_string(smart_str *str, const zend_module_entry *module, const char *indent);
311312
static void _zend_extension_string(smart_str *str, const zend_extension *extension, const char *indent);
@@ -330,6 +331,8 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, const
330331
kind = "Interface";
331332
} else if (ce->ce_flags & ZEND_ACC_TRAIT) {
332333
kind = "Trait";
334+
} else if (ce->ce_flags & ZEND_ACC_ENUM) {
335+
kind = "Enum";
333336
}
334337
smart_str_append_printf(str, "%s%s [ ", indent, kind);
335338
}
@@ -345,6 +348,8 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, const
345348
smart_str_append_printf(str, "interface ");
346349
} else if (ce->ce_flags & ZEND_ACC_TRAIT) {
347350
smart_str_append_printf(str, "trait ");
351+
} else if (ce->ce_flags & ZEND_ACC_ENUM) {
352+
smart_str_append_printf(str, "enum ");
348353
} else {
349354
if (ce->ce_flags & (ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
350355
smart_str_append_printf(str, "abstract ");
@@ -362,6 +367,12 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, const
362367
smart_str_append_printf(str, " extends %s", ZSTR_VAL(ce->parent->name));
363368
}
364369

370+
// Show backing type of enums
371+
if ((ce->ce_flags & ZEND_ACC_ENUM) && (ce->enum_backing_type != IS_UNDEF)) {
372+
smart_str_append_printf(str,
373+
ce->enum_backing_type == IS_STRING ? ": string" : ": int"
374+
);
375+
}
365376
if (ce->num_interfaces) {
366377
uint32_t i;
367378

@@ -384,23 +395,49 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, const
384395
}
385396

386397
/* Constants */
387-
smart_str_append_printf(str, "\n");
388-
count = zend_hash_num_elements(&ce->constants_table);
389-
smart_str_append_printf(str, "%s - Constants [%d] {\n", indent, count);
390-
if (count > 0) {
398+
uint32_t total_count = zend_hash_num_elements(&ce->constants_table);
399+
uint32_t constant_count = 0;
400+
uint32_t enum_case_count = 0;
401+
smart_str constant_str = {0};
402+
smart_str enum_case_str = {0};
403+
/* So that we don't need to loop through all of the constants multiple
404+
* times (count the constants vs. enum cases, print the constants, print
405+
* the enum cases) use some temporary helper smart strings. */
406+
if (total_count > 0) {
391407
zend_string *key;
392408
zend_class_constant *c;
393409

394410
ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(CE_CONSTANTS_TABLE(ce), key, c) {
395-
_class_const_string(str, key, c, ZSTR_VAL(sub_indent));
411+
if (ZEND_CLASS_CONST_FLAGS(c) & ZEND_CLASS_CONST_IS_CASE) {
412+
_enum_case_string(&enum_case_str, key, c, ZSTR_VAL(sub_indent));
413+
enum_case_count++;
414+
} else {
415+
_class_const_string(&constant_str, key, c, ZSTR_VAL(sub_indent));
416+
constant_count++;
417+
}
396418
if (UNEXPECTED(EG(exception))) {
397419
zend_string_release(sub_indent);
420+
smart_str_free(&enum_case_str);
421+
smart_str_free(&constant_str);
398422
return;
399423
}
400424
} ZEND_HASH_FOREACH_END();
401425
}
426+
// Enum cases go first, but the heading is only shown if there are any
427+
if (enum_case_count) {
428+
smart_str_appendc(str, '\n');
429+
smart_str_append_printf(str, "%s - Enum cases [%d] {\n", indent, enum_case_count);
430+
smart_str_append_smart_str(str, &enum_case_str);
431+
smart_str_append_printf(str, "%s }\n", indent);
432+
}
433+
smart_str_appendc(str, '\n');
434+
smart_str_append_printf(str, "%s - Constants [%d] {\n", indent, constant_count);
435+
smart_str_append_smart_str(str, &constant_str);
402436
smart_str_append_printf(str, "%s }\n", indent);
403437

438+
smart_str_free(&enum_case_str);
439+
smart_str_free(&constant_str);
440+
404441
/* Static properties */
405442
/* counting static properties */
406443
count = zend_hash_num_elements(&ce->properties_info);
@@ -626,6 +663,32 @@ static void _class_const_string(smart_str *str, const zend_string *name, zend_cl
626663
}
627664
/* }}} */
628665

666+
static void _enum_case_string(smart_str *str, const zend_string *name, zend_class_constant *c, const char *indent)
667+
{
668+
if (Z_TYPE(c->value) == IS_CONSTANT_AST && zend_update_class_constant(c, name, c->ce) == FAILURE) {
669+
return;
670+
}
671+
672+
if (c->doc_comment) {
673+
smart_str_append_printf(str, "%s%s\n", indent, ZSTR_VAL(c->doc_comment));
674+
}
675+
smart_str_append_printf(str, "%sCase %s", indent, ZSTR_VAL(name));
676+
if (c->ce->enum_backing_type == IS_UNDEF) {
677+
// No value
678+
smart_str_appendc(str, '\n');
679+
} else {
680+
/* Has a value, which is the enum instance, get the value from that.
681+
* We know it must be either a string or integer so no need
682+
* for the IS_ARRAY or IS_OBJECT handling that _class_const_string()
683+
* requires. */
684+
zval *enum_val = zend_enum_fetch_case_value(Z_OBJ(c->value));
685+
zend_string *tmp_value_str;
686+
zend_string *value_str = zval_get_tmp_string(enum_val, &tmp_value_str);
687+
smart_str_append_printf(str, " = %s\n", ZSTR_VAL(value_str));
688+
zend_tmp_string_release(tmp_value_str);
689+
}
690+
}
691+
629692
static zend_op *get_recv_op(const zend_op_array *op_array, uint32_t offset)
630693
{
631694
zend_op *op = op_array->opcodes;

‎ext/reflection/tests/ReflectionEnumUnitCase_getEnum.phpt‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ echo (new ReflectionEnumUnitCase(Foo::class, 'Bar'))->getEnum();
1111

1212
?>
1313
--EXPECTF--
14-
Class [ <user> final class Foo implements UnitEnum ] {
14+
Enum [ <user> enum Foo implements UnitEnum ] {
1515
@@ %sReflectionEnumUnitCase_getEnum.php 3-5
1616

17-
- Constants [1] {
18-
Constant [ public Foo Bar ] { Object }
17+
- Enum cases [1] {
18+
Case Bar
19+
}
20+
21+
- Constants [0] {
1922
}
2023

2124
- Static properties [0] {

‎ext/reflection/tests/ReflectionEnum_toString.phpt‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ echo new ReflectionEnum(Foo::class);
1111

1212
?>
1313
--EXPECTF--
14-
Class [ <user> final class Foo implements UnitEnum ] {
14+
Enum [ <user> enum Foo implements UnitEnum ] {
1515
@@ %sReflectionEnum_toString.php 3-5
1616

17-
- Constants [1] {
18-
Constant [ public Foo Bar ] { Object }
17+
- Enum cases [1] {
18+
Case Bar
19+
}
20+
21+
- Constants [0] {
1922
}
2023

2124
- Static properties [0] {

‎ext/reflection/tests/ReflectionEnum_toString_backed_int.phpt‎

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,15 @@ var_export( MyBool::cases() );
2828

2929
?>
3030
--EXPECTF--
31-
Class [ <user> final class MyBool implements MyStringable, UnitEnum, BackedEnum ] {
31+
Enum [ <user> enum MyBool: int implements MyStringable, UnitEnum, BackedEnum ] {
3232
@@ %sReflectionEnum_toString_backed_int.php 7-16
3333

34-
- Constants [3] {
35-
Constant [ public MyBool MyFalse ] { Object }
36-
Constant [ public MyBool MyTrue ] { Object }
34+
- Enum cases [2] {
35+
Case MyFalse = 0
36+
Case MyTrue = 1
37+
}
38+
39+
- Constants [1] {
3740
Constant [ public MyBool OtherTrue ] { Object }
3841
}
3942

@@ -81,12 +84,15 @@ Class [ <user> final class MyBool implements MyStringable, UnitEnum, BackedEnum
8184
}
8285
}
8386

84-
Class [ <user> final class MyBool implements MyStringable, UnitEnum, BackedEnum ] {
87+
Enum [ <user> enum MyBool: int implements MyStringable, UnitEnum, BackedEnum ] {
8588
@@ %sReflectionEnum_toString_backed_int.php 7-16
8689

87-
- Constants [3] {
88-
Constant [ public MyBool MyFalse ] { Object }
89-
Constant [ public MyBool MyTrue ] { Object }
90+
- Enum cases [2] {
91+
Case MyFalse = 0
92+
Case MyTrue = 1
93+
}
94+
95+
- Constants [1] {
9096
Constant [ public MyBool OtherTrue ] { Object }
9197
}
9298

‎ext/reflection/tests/ReflectionEnum_toString_backed_string.phpt‎

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,15 @@ var_export( MyBool::cases() );
2828

2929
?>
3030
--EXPECTF--
31-
Class [ <user> final class MyBool implements MyStringable, UnitEnum, BackedEnum ] {
31+
Enum [ <user> enum MyBool: string implements MyStringable, UnitEnum, BackedEnum ] {
3232
@@ %sReflectionEnum_toString_backed_string.php 7-16
3333

34-
- Constants [3] {
35-
Constant [ public MyBool MyFalse ] { Object }
36-
Constant [ public MyBool MyTrue ] { Object }
34+
- Enum cases [2] {
35+
Case MyFalse = ~FALSE~
36+
Case MyTrue = ~TRUE~
37+
}
38+
39+
- Constants [1] {
3740
Constant [ public MyBool OtherTrue ] { Object }
3841
}
3942

@@ -81,12 +84,15 @@ Class [ <user> final class MyBool implements MyStringable, UnitEnum, BackedEnum
8184
}
8285
}
8386

84-
Class [ <user> final class MyBool implements MyStringable, UnitEnum, BackedEnum ] {
87+
Enum [ <user> enum MyBool: string implements MyStringable, UnitEnum, BackedEnum ] {
8588
@@ %sReflectionEnum_toString_backed_string.php 7-16
8689

87-
- Constants [3] {
88-
Constant [ public MyBool MyFalse ] { Object }
89-
Constant [ public MyBool MyTrue ] { Object }
90+
- Enum cases [2] {
91+
Case MyFalse = ~FALSE~
92+
Case MyTrue = ~TRUE~
93+
}
94+
95+
- Constants [1] {
9096
Constant [ public MyBool OtherTrue ] { Object }
9197
}
9298

‎ext/reflection/tests/ReflectionEnum_toString_unbacked.phpt‎

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,17 @@ var_export( Suit::cases() );
3030

3131
?>
3232
--EXPECTF--
33-
Class [ <user> final class Suit implements MyStringable, UnitEnum ] {
33+
Enum [ <user> enum Suit implements MyStringable, UnitEnum ] {
3434
@@ %sReflectionEnum_toString_unbacked.php 7-18
3535

36-
- Constants [5] {
37-
Constant [ public Suit Hearts ] { Object }
38-
Constant [ public Suit Diamonds ] { Object }
39-
Constant [ public Suit Clubs ] { Object }
40-
Constant [ public Suit Spades ] { Object }
36+
- Enum cases [4] {
37+
Case Hearts
38+
Case Diamonds
39+
Case Clubs
40+
Case Spades
41+
}
42+
43+
- Constants [1] {
4144
Constant [ public Suit OtherHearts ] { Object }
4245
}
4346

@@ -68,14 +71,17 @@ Class [ <user> final class Suit implements MyStringable, UnitEnum ] {
6871
}
6972
}
7073

71-
Class [ <user> final class Suit implements MyStringable, UnitEnum ] {
74+
Enum [ <user> enum Suit implements MyStringable, UnitEnum ] {
7275
@@ %sReflectionEnum_toString_unbacked.php 7-18
7376

74-
- Constants [5] {
75-
Constant [ public Suit Hearts ] { Object }
76-
Constant [ public Suit Diamonds ] { Object }
77-
Constant [ public Suit Clubs ] { Object }
78-
Constant [ public Suit Spades ] { Object }
77+
- Enum cases [4] {
78+
Case Hearts
79+
Case Diamonds
80+
Case Clubs
81+
Case Spades
82+
}
83+
84+
- Constants [1] {
7985
Constant [ public Suit OtherHearts ] { Object }
8086
}
8187

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /