mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
zend_language_parser: Backup / restore doc comment when parsing attributes (#20896)
Attributes may themselves contain elements which can have a doc comment on their own (namely Closures). A doc comment before the attribute list is generally understood as belonging to the symbol having the attributes. Fixes php/php-src#20895.
This commit is contained in:
2
NEWS
2
NEWS
@@ -13,6 +13,8 @@ PHP NEWS
|
||||
. Fix OSS-Fuzz #472563272 (Borked block_pass JMP[N]Z optimization). (ilutov)
|
||||
. Fixed bug GH-20914 (Internal enums can be cloned and compared). (Arnaud)
|
||||
. Fix OSS-Fuzz #474613951 (Leaked parent property default value). (ilutov)
|
||||
. Fixed bug GH-20895 (ReflectionProperty does not return the PHPDoc of a
|
||||
property if it contains an attribute with a Closure). (timwolla)
|
||||
|
||||
- MbString:
|
||||
. Fixed bug GH-20833 (mb_str_pad() divide by zero if padding string is
|
||||
|
||||
@@ -379,7 +379,7 @@ attribute_group:
|
||||
;
|
||||
|
||||
attribute:
|
||||
T_ATTRIBUTE attribute_group possible_comma ']' { $$ = $2; }
|
||||
T_ATTRIBUTE backup_doc_comment attribute_group possible_comma ']' { $$ = $3; CG(doc_comment) = $2; }
|
||||
;
|
||||
|
||||
attributes:
|
||||
|
||||
108
ext/reflection/tests/gh20895.phpt
Normal file
108
ext/reflection/tests/gh20895.phpt
Normal file
@@ -0,0 +1,108 @@
|
||||
--TEST--
|
||||
GH-20895: ReflectionProperty does not return the PHPDoc of a property if it contains an attribute with a Closure
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
/** Foo */
|
||||
#[Attr(
|
||||
/** Closure 1 */
|
||||
static function() { },
|
||||
/** Closure 2 */
|
||||
static function() { },
|
||||
)]
|
||||
class Foo {
|
||||
/** Foo::$bar */
|
||||
#[Attr(
|
||||
/** Closure 3 */
|
||||
static function() { },
|
||||
/** Closure 4 */
|
||||
static function() { },
|
||||
)]
|
||||
#[Attr(
|
||||
/** Closure 5 */
|
||||
static function() { },
|
||||
)]
|
||||
public $bar;
|
||||
|
||||
/** Foo::bar() */
|
||||
#[Attr(
|
||||
/** Closure 6 */
|
||||
static function() { },
|
||||
)]
|
||||
public function bar() { }
|
||||
}
|
||||
|
||||
/** foo() */
|
||||
#[Attr(
|
||||
/** Closure 7 */
|
||||
static function() { },
|
||||
)]
|
||||
function foo() { }
|
||||
|
||||
#[Attr(
|
||||
/** Closure 8 */
|
||||
static function() { },
|
||||
)]
|
||||
/** bar() */
|
||||
function bar() { }
|
||||
|
||||
/** baz() */
|
||||
#[Attr(
|
||||
static function() { },
|
||||
)]
|
||||
function baz() { }
|
||||
|
||||
var_dump((new ReflectionClass(Foo::class))->getDocComment());
|
||||
foreach ((new ReflectionClass(Foo::class))->getAttributes() as $attribute) {
|
||||
foreach ($attribute->getArguments() as $argument) {
|
||||
var_dump((new ReflectionFunction($argument))->getDocComment());
|
||||
}
|
||||
}
|
||||
var_dump((new ReflectionProperty(Foo::class, 'bar'))->getDocComment());
|
||||
foreach ((new ReflectionProperty(Foo::class, 'bar'))->getAttributes() as $attribute) {
|
||||
foreach ($attribute->getArguments() as $argument) {
|
||||
var_dump((new ReflectionFunction($argument))->getDocComment());
|
||||
}
|
||||
}
|
||||
var_dump((new ReflectionMethod(Foo::class, 'bar'))->getDocComment());
|
||||
foreach ((new ReflectionMethod(Foo::class, 'bar'))->getAttributes() as $attribute) {
|
||||
foreach ($attribute->getArguments() as $argument) {
|
||||
var_dump((new ReflectionFunction($argument))->getDocComment());
|
||||
}
|
||||
}
|
||||
var_dump((new ReflectionFunction('foo'))->getDocComment());
|
||||
foreach ((new ReflectionFunction('foo'))->getAttributes() as $attribute) {
|
||||
foreach ($attribute->getArguments() as $argument) {
|
||||
var_dump((new ReflectionFunction($argument))->getDocComment());
|
||||
}
|
||||
}
|
||||
var_dump((new ReflectionFunction('bar'))->getDocComment());
|
||||
foreach ((new ReflectionFunction('bar'))->getAttributes() as $attribute) {
|
||||
foreach ($attribute->getArguments() as $argument) {
|
||||
var_dump((new ReflectionFunction($argument))->getDocComment());
|
||||
}
|
||||
}
|
||||
var_dump((new ReflectionFunction('baz'))->getDocComment());
|
||||
foreach ((new ReflectionFunction('baz'))->getAttributes() as $attribute) {
|
||||
foreach ($attribute->getArguments() as $argument) {
|
||||
var_dump((new ReflectionFunction($argument))->getDocComment());
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
string(10) "/** Foo */"
|
||||
string(16) "/** Closure 1 */"
|
||||
string(16) "/** Closure 2 */"
|
||||
string(16) "/** Foo::$bar */"
|
||||
string(16) "/** Closure 3 */"
|
||||
string(16) "/** Closure 4 */"
|
||||
string(16) "/** Closure 5 */"
|
||||
string(17) "/** Foo::bar() */"
|
||||
string(16) "/** Closure 6 */"
|
||||
string(12) "/** foo() */"
|
||||
string(16) "/** Closure 7 */"
|
||||
string(12) "/** bar() */"
|
||||
string(16) "/** Closure 8 */"
|
||||
string(12) "/** baz() */"
|
||||
bool(false)
|
||||
Reference in New Issue
Block a user