Support doc comments on enum cases (#6984)

Because php supports doc comments on class constants, I believe it would also
make sense to support them on enum cases.

I don't have strong opinions about whether attributes should be moved to be the
last element or whether the doc comment should go after the attribute,
but the ast will likely change again before php 8.1 is stable.
So far, all attributes are the last ast child node.

I didn't notice that doc comments weren't implemented due to
https://github.com/php/php-src/pull/6489 being a large change.

https://wiki.php.net/rfc/enumerations
did not mention whether or not doc comments were meant to be supported
This commit is contained in:
Tyson Andre 2021-05-14 15:25:03 -04:00 committed by GitHub
parent 87e4970ebc
commit d60bc0e2d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 39 additions and 10 deletions

View file

@ -2201,8 +2201,8 @@ simple_list:
zend_ast_export_name(str, ast->child[1], 0, indent); zend_ast_export_name(str, ast->child[1], 0, indent);
APPEND_DEFAULT_VALUE(2); APPEND_DEFAULT_VALUE(2);
case ZEND_AST_ENUM_CASE: case ZEND_AST_ENUM_CASE:
if (ast->child[2]) { if (ast->child[3]) {
zend_ast_export_attributes(str, ast->child[2], indent, 1); zend_ast_export_attributes(str, ast->child[3], indent, 1);
} }
smart_str_appends(str, "case "); smart_str_appends(str, "case ");
zend_ast_export_name(str, ast->child[0], 0, indent); zend_ast_export_name(str, ast->child[0], 0, indent);
@ -2329,14 +2329,12 @@ zend_ast * ZEND_FASTCALL zend_ast_with_attributes(zend_ast *ast, zend_ast *attr)
ast->child[2] = attr; ast->child[2] = attr;
break; break;
case ZEND_AST_PARAM: case ZEND_AST_PARAM:
case ZEND_AST_ENUM_CASE:
ast->child[3] = attr; ast->child[3] = attr;
break; break;
case ZEND_AST_CLASS_CONST_GROUP: case ZEND_AST_CLASS_CONST_GROUP:
ast->child[1] = attr; ast->child[1] = attr;
break; break;
case ZEND_AST_ENUM_CASE:
ast->child[2] = attr;
break;
EMPTY_SWITCH_DEFAULT_CASE() EMPTY_SWITCH_DEFAULT_CASE()
} }

View file

@ -159,7 +159,6 @@ enum _zend_ast_kind {
ZEND_AST_PROP_GROUP, ZEND_AST_PROP_GROUP,
ZEND_AST_PROP_ELEM, ZEND_AST_PROP_ELEM,
ZEND_AST_CONST_ELEM, ZEND_AST_CONST_ELEM,
ZEND_AST_ENUM_CASE,
// Pseudo node for initializing enums // Pseudo node for initializing enums
ZEND_AST_CONST_ENUM_INIT, ZEND_AST_CONST_ENUM_INIT,
@ -167,6 +166,7 @@ enum _zend_ast_kind {
/* 4 child nodes */ /* 4 child nodes */
ZEND_AST_FOR = 4 << ZEND_AST_NUM_CHILDREN_SHIFT, ZEND_AST_FOR = 4 << ZEND_AST_NUM_CHILDREN_SHIFT,
ZEND_AST_FOREACH, ZEND_AST_FOREACH,
ZEND_AST_ENUM_CASE,
/* 5 child nodes */ /* 5 child nodes */
ZEND_AST_PARAM = 5 << ZEND_AST_NUM_CHILDREN_SHIFT, ZEND_AST_PARAM = 5 << ZEND_AST_NUM_CHILDREN_SHIFT,

View file

@ -7748,11 +7748,19 @@ static void zend_compile_enum_case(zend_ast *ast)
zval value_zv; zval value_zv;
zend_const_expr_to_zval(&value_zv, &const_enum_init_ast); zend_const_expr_to_zval(&value_zv, &const_enum_init_ast);
zend_class_constant *c = zend_declare_class_constant_ex(enum_class, enum_case_name, &value_zv, ZEND_ACC_PUBLIC, NULL);
/* Doc comment has been appended as second last element in ZEND_AST_ENUM ast - attributes are conventionally last */
zend_ast *doc_comment_ast = ast->child[2];
zend_string *doc_comment = NULL;
if (doc_comment_ast) {
doc_comment = zend_string_copy(zend_ast_get_str(doc_comment_ast));
}
zend_class_constant *c = zend_declare_class_constant_ex(enum_class, enum_case_name, &value_zv, ZEND_ACC_PUBLIC, doc_comment);
ZEND_CLASS_CONST_FLAGS(c) |= ZEND_CLASS_CONST_IS_CASE; ZEND_CLASS_CONST_FLAGS(c) |= ZEND_CLASS_CONST_IS_CASE;
zend_ast_destroy(const_enum_init_ast); zend_ast_destroy(const_enum_init_ast);
zend_ast *attr_ast = ast->child[2]; zend_ast *attr_ast = ast->child[3];
if (attr_ast) { if (attr_ast) {
zend_compile_attributes(&c->attributes, attr_ast, 0, ZEND_ATTRIBUTE_TARGET_CLASS_CONST); zend_compile_attributes(&c->attributes, attr_ast, 0, ZEND_ATTRIBUTE_TARGET_CLASS_CONST);
} }

View file

@ -607,8 +607,8 @@ enum_backing_type:
; ;
enum_case: enum_case:
T_CASE identifier enum_case_expr ';' T_CASE backup_doc_comment identifier enum_case_expr ';'
{ $$ = zend_ast_create(ZEND_AST_ENUM_CASE, $2, $3, NULL); } { $$ = zend_ast_create(ZEND_AST_ENUM_CASE, $3, $4, ($2 ? zend_ast_create_zval_from_str($2) : NULL), NULL); }
; ;
enum_case_expr: enum_case_expr:

View file

@ -0,0 +1,23 @@
--TEST--
ReflectionEnumUnitCase::getDocComment()
--FILE--
<?php
// enum cases should support doc comments, like class constants.
enum Foo {
/** Example doc comment */
case Bar;
case Baz;
}
var_dump((new ReflectionEnumUnitCase(Foo::class, 'Bar'))->getDocComment());
var_dump((new ReflectionEnumUnitCase(Foo::class, 'Baz'))->getDocComment());
var_dump((new ReflectionClassConstant(Foo::class, 'Bar'))->getDocComment());
var_dump((new ReflectionClassConstant(Foo::class, 'Baz'))->getDocComment());
?>
--EXPECT--
string(26) "/** Example doc comment */"
bool(false)
string(26) "/** Example doc comment */"
bool(false)