Skip to content

Commit

Permalink
Support doc comments on enum cases (php#6984)
Browse files Browse the repository at this point in the history
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
php#6489 being a large change.

https://wiki.php.net/rfc/enumerations
did not mention whether or not doc comments were meant to be supported
  • Loading branch information
TysonAndre authored May 14, 2021
1 parent 87e4970 commit d60bc0e
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 10 deletions.
8 changes: 3 additions & 5 deletions Zend/zend_ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -2201,8 +2201,8 @@ static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int prio
zend_ast_export_name(str, ast->child[1], 0, indent);
APPEND_DEFAULT_VALUE(2);
case ZEND_AST_ENUM_CASE:
if (ast->child[2]) {
zend_ast_export_attributes(str, ast->child[2], indent, 1);
if (ast->child[3]) {
zend_ast_export_attributes(str, ast->child[3], indent, 1);
}
smart_str_appends(str, "case ");
zend_ast_export_name(str, ast->child[0], 0, indent);
Expand Down Expand Up @@ -2329,14 +2329,12 @@ zend_ast * ZEND_FASTCALL zend_ast_with_attributes(zend_ast *ast, zend_ast *attr)
ast->child[2] = attr;
break;
case ZEND_AST_PARAM:
case ZEND_AST_ENUM_CASE:
ast->child[3] = attr;
break;
case ZEND_AST_CLASS_CONST_GROUP:
ast->child[1] = attr;
break;
case ZEND_AST_ENUM_CASE:
ast->child[2] = attr;
break;
EMPTY_SWITCH_DEFAULT_CASE()
}

Expand Down
2 changes: 1 addition & 1 deletion Zend/zend_ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,14 +159,14 @@ enum _zend_ast_kind {
ZEND_AST_PROP_GROUP,
ZEND_AST_PROP_ELEM,
ZEND_AST_CONST_ELEM,
ZEND_AST_ENUM_CASE,

// Pseudo node for initializing enums
ZEND_AST_CONST_ENUM_INIT,

/* 4 child nodes */
ZEND_AST_FOR = 4 << ZEND_AST_NUM_CHILDREN_SHIFT,
ZEND_AST_FOREACH,
ZEND_AST_ENUM_CASE,

/* 5 child nodes */
ZEND_AST_PARAM = 5 << ZEND_AST_NUM_CHILDREN_SHIFT,
Expand Down
12 changes: 10 additions & 2 deletions Zend/zend_compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -7748,11 +7748,19 @@ static void zend_compile_enum_case(zend_ast *ast)

zval value_zv;
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_ast_destroy(const_enum_init_ast);

zend_ast *attr_ast = ast->child[2];
zend_ast *attr_ast = ast->child[3];
if (attr_ast) {
zend_compile_attributes(&c->attributes, attr_ast, 0, ZEND_ATTRIBUTE_TARGET_CLASS_CONST);
}
Expand Down
4 changes: 2 additions & 2 deletions Zend/zend_language_parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -607,8 +607,8 @@ enum_backing_type:
;

enum_case:
T_CASE identifier enum_case_expr ';'
{ $$ = zend_ast_create(ZEND_AST_ENUM_CASE, $2, $3, NULL); }
T_CASE backup_doc_comment identifier enum_case_expr ';'
{ $$ = zend_ast_create(ZEND_AST_ENUM_CASE, $3, $4, ($2 ? zend_ast_create_zval_from_str($2) : NULL), NULL); }
;

enum_case_expr:
Expand Down
23 changes: 23 additions & 0 deletions ext/reflection/tests/ReflectionEnumUnitCase_getDocComment.phpt
Original file line number Diff line number Diff line change
@@ -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)

0 comments on commit d60bc0e

Please sign in to comment.