nikic / PHP-Parser

A PHP parser written in PHP

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Syntax error with readonly and DNF tokens

mrsuh opened this issue · comments

How to reproduce:

composer req nikic/php-parser:v4.15.2

test.php

<?php

require_once __DIR__ . '/vendor/autoload.php';

use PhpParser\ParserFactory;

$code = <<<'CODE'
<?php

class A {}
class B {}

class Container  {
    public readonly (A&B)|null $property; // <-- error
}
CODE;

$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
$parser->parse($code);

This error is only reproducible with PHP < 8.2

docker run -it --rm -v "$PWD":/app php:7.4-cli php /app/test.php
docker run -it --rm -v "$PWD":/app php:8.0-cli php /app/test.php
docker run -it --rm -v "$PWD":/app php:8.1-cli php /app/test.php
Fatal error: Uncaught PhpParser\Error: Syntax error, unexpected '(', expecting T_VARIABLE on line 7 in /app/vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php:318
Stack trace:
#0 /app/vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php(159): PhpParser\ParserAbstract->doParse()
#1 /app/test.php(28): PhpParser\ParserAbstract->parse('<?php\n\nclass A ...')
#2 {main}
  thrown in /app/vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php on line 318

I fixed error for PHP < 8.1 like this.

Error for PHP 8.1 is more complicated because of function token_get_all().
How to reproduce token_get_all() error for PHP 8.1:

tokens.php

<?php

$code = <<<'CODE'
<?php

class A {}
class B {}

class Container  {
    public readonly (A&B)|null $property1;
    public readonly null|(A&B) $property2;
}
CODE;

foreach (token_get_all($code) as $token) {
    if (is_array($token)) {
        echo "Line {$token[2]}: ", token_name($token[0]), " ('{$token[1]}')", PHP_EOL;
    }
}
docker run -it --rm -v "$PWD":/app php:8.1-cli php /app/tokens.php | grep readonly
Line 7: T_STRING ('readonly')
Line 8: T_READONLY ('readonly')

In first case readonly is T_STRING and in second case readonly is T_READONLY;
Should I make an issue in php-src repository about this?

Anyway we should handle this behavior. I don't know how to make it better so I did this

PR: #911

This was fixed on the master branch already, I've backported the change in 8863f92.