PHP-Parser icon indicating copy to clipboard operation
PHP-Parser copied to clipboard

Parser does not see docComments between attributes and class declaration

Open ondrejmirtes opened this issue 4 years ago • 4 comments

Given this PHP code:

<?php

#[AttributeStub()]
/**
 * @template T
 */
class ClassStub
{
	/**
	 * @param T $var
	 */
	public function __construct(public $var) {}
}

PHP itself sees both attribute and doc comment: https://3v4l.org/Pe17n

But PHP-Parser doesn't (bin/php-parse output on PHP 7.4):

array(
    0: Stmt_Class(
        attrGroups: array(
            0: AttributeGroup(
                attrs: array(
                    0: Attribute(
                        name: Name(
                            parts: array(
                                0: AttributeStub
                            )
                        )
                        args: array(
                        )
                    )
                )
            )
        )
        flags: 0
        name: Identifier(
            name: ClassStub
        )
        extends: null
        implements: array(
        )
        stmts: array(
            0: Stmt_ClassMethod(
                attrGroups: array(
                )
                flags: MODIFIER_PUBLIC (1)
                byRef: false
                name: Identifier(
                    name: __construct
                )
                params: array(
                    0: Param(
                        attrGroups: array(
                        )
                        flags: MODIFIER_PUBLIC (1)
                        type: null
                        byRef: false
                        variadic: false
                        var: Expr_Variable(
                            name: var
                        )
                        default: null
                    )
                )
                returnType: null
                stmts: array(
                )
                comments: array(
                    0: /**
                     * @param T $var
                     */
                )
            )
        )
    )
)

Original report: https://github.com/phpstan/phpstan/issues/4633

ondrejmirtes avatar Mar 01 '21 15:03 ondrejmirtes

The parser only collects comments before a node -- as the attributes are considered part of the class, the doc comment ends up being "inside" the class, and thus lost. It's not really possible to fix this with the current architecture.

nikic avatar Apr 25 '21 20:04 nikic

Alright, thanks! This is probably the same issue:

class HelloWorld
{
    #[Groups]
    #[Valid]
    /** @var \stdClass[]|null */
    public ?array $damages = null;
}

ondrejmirtes avatar May 05 '21 11:05 ondrejmirtes

given this php code

        if (
            /** @authdoc-c (i18n="foobar") */
            !check("view", "foobar") &&
            /** @authdoc-c (i18n="barfoo") */
            (empty($myGroups[$groupId]) || !check($myGroups[$groupId], "barfoo"))
        )

the second docblock is not seen as well. I guess it is a similar problem.

bwl21 avatar Oct 24 '21 17:10 bwl21

It seems to me, using $node->name->getStartLine() is the most reliable option right now. It's not always correct, because we can have

#[Attr]
final
class
A {}

But it's less likely than

#[Attr]
final class A {}

vudaltsov avatar Sep 24 '23 12:09 vudaltsov