[PHP 8.6] ReflectionParameter::getDocComment() support - #227
Merged
Conversation
PHP 8.6 allows doc comments on function and method parameters and exposes them through the native `ReflectionParameter::getDocComment(): string|false`. Implement the method statically from the AST so it is available on every supported PHP version. PHP-Parser attaches a doc comment to the `Param` node only when the comment directly precedes the parameter; comments placed after an attribute group, after the type or inside a default value expression land on nested nodes. The whole parameter sub-tree is therefore scanned and the last doc comment in source order wins, which mirrors how PHP resolves the doc comment of a parameter. Add `tests/Stub/FileWithParameters86.php` covering plain, variadic, by-reference, nullable, union-typed, promoted and attributed parameters as well as non-doc comments, and parity tests that compare the statically derived values with native reflection on PHP >= 8.6. Known parity gap: a doc comment written after the parameter it documents is still reported by native reflection but is attached by PHP-Parser to the following node, so the engine returns false. This is documented and covered by a dedicated test. Refs #221 Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Sy8BcM8ivUEpu8uVm7wADn
…rameter Cover the second shape of the known trailing doc comment parity gap, where another parameter follows the comment. Verified against PHP 8.6.0beta1 and nikic/php-parser 5.8.0: native reflection reports the comment for the parameter it follows, while PHP-Parser discards a comment placed between the end of a parameter and the separating comma altogether. The comment is therefore lost rather than mis-attributed to the next parameter, and the engine returns false for both parameters. Add `twoParametersWithTrailingDocComment86()` to the stub, pin both the engine and the native side in a dedicated test, and correct the limitation paragraph in the documentation accordingly. Refs #221 Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Sy8BcM8ivUEpu8uVm7wADn
Member
Author
|
@claude need to rebase, or merge master here to update checks in CI pipeline naming |
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Sy8BcM8ivUEpu8uVm7wADn
Member
Author
|
Done — merged Also brought Generated by Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #221 (part of epic #219).
What
PHP 8.6 allows doc comments on function/method parameters and exposes them through the new native
ReflectionParameter::getDocComment(): string|false. This PR implements the same method statically from the AST, so it is available on every supported PHP version, not only on 8.6.Changes
src/ReflectionParameter.php— newgetDocComment(): string|false(signature-compatible with the PHP 8.6 parent; on 8.5 it is simply an extra method, the 8.5 parent has none).tests/Stub/FileWithParameters86.php— new stub with the doc-comment matrix. It contains only ordinary comments, so it parses and loads on every supported PHP version and is included by the test to allow native comparison.tests/ReflectionParameterTest.php— dedicatedtestGetDocComment()parity test, two tests pinning the known trailing-comment gap, plusgetDocCommentadded to the generic getter parity matrix when running on PHP >= 8.6.docs/reflection_parameter.md— documents the method and the known limitation.Resolution strategy
PHP-Parser attaches a doc comment to the
Paramnode itself only when the comment directly precedes the parameter declaration. When the comment sits inside the declaration it ends up on a nested node instead — verified with the bundlednikic/php-parserv5.8.0:/** doc */ string $aParam/** doc */ #[Attr] string $aParam#[Attr] /** doc */ string $aIdentifier(the type)#[A] /** doc */ #[B] string $aAttributeGroupint $a = /** doc */ 5Therefore the implementation scans the whole parameter sub-tree and picks the last doc comment in source order, which is exactly how PHP itself resolves a parameter's doc comment (its lexer remembers the most recent doc-comment token). Non-doc comments (
/* … */,// …) never reset it, and the last of several doc comments wins — both verified against the 8.6 binary.Verified parity against PHP 8.6.0beta1
Every parameter in the new stub returns byte-for-byte the same value as native reflection: leading doc comments, variadic, by-reference, nullable, union-typed, defaults (scalar/array), promoted constructor properties (public/protected), static methods, doc comment before and after attributes, several consecutive doc comments, doc comment followed by a block comment, plus the negative cases (no comment, block comment, line comment). Function/method doc comments correctly do not leak into the first parameter.
Also checked: native
var_dump()/(array)cast ofReflectionParameteron 8.6 still exposes onlyname, so__debugInfo()/InternalPropertiesEmulationTraitneeded no change.testCoverAllMethodsforReflectionParameternow passes on 8.6 (it would otherwise reportgetDocCommentas missing).Known parity gap
A doc comment written after the parameter it documents is reported by native reflection as belonging to that parameter, because PHP records the last doc-comment token seen while reducing the parameter rule. PHP-Parser attaches every comment to the node that follows it, and a comment sitting between the end of a parameter and the separating comma is discarded entirely, so such a trailing comment never reaches the AST at all:
Note that the comment is not mis-attributed to the following parameter — it is simply lost. This position is pathological and cannot be recovered without access to the token stream (the comma position is not available on the AST). It is documented in
docs/reflection_parameter.md, in the stub, and pinned from both sides bytestTrailingDocCommentIsAKnownParityGap()andtestTrailingDocCommentIsLostWhenAnotherParameterFollows(), which also assert the divergent native behaviour on 8.6 so a future change in php-src or PHP-Parser is noticed.Local results
vendor/bin/phpunit(PHP 8.5.9)ReflectionPropertyTest::testCoverAllMethods)php8.6 vendor/bin/phpunit(PHP 8.6.0beta1)vendor/bin/phpstan analyse src --no-progress(level 10)[OK] No errors— nophpstan.neonchanges neededBaseline on
masterwas 13743 tests on 8.5; the new tests add 21 cases on 8.5 and 149 on 8.6 (the extra ones come fromgetDocCommentjoining the generic getter parity matrix).🤖 Generated with Claude Code
https://claude.ai/code/session_01Sy8BcM8ivUEpu8uVm7wADn