Support readonly anonymous classes

This commit is contained in:
Nikita Popov 2023-05-20 21:17:44 +02:00
parent 5c267f55c9
commit 91da19147b
9 changed files with 948 additions and 921 deletions

View File

@ -1076,8 +1076,8 @@ expr:
;
anonymous_class:
optional_attributes T_CLASS ctor_arguments extends_from implements_list '{' class_statement_list '}'
{ $$ = array(Stmt\Class_[null, ['type' => 0, 'extends' => $4, 'implements' => $5, 'stmts' => $7, 'attrGroups' => $1]], $3);
optional_attributes class_entry_type ctor_arguments extends_from implements_list '{' class_statement_list '}'
{ $$ = array(Stmt\Class_[null, ['type' => $2, 'extends' => $4, 'implements' => $5, 'stmts' => $7, 'attrGroups' => $1]], $3);
$this->checkClass($$[0], -1); }
;

View File

@ -18,6 +18,8 @@ use PhpParser\Node\Expr;
class PrintableNewAnonClassNode extends Expr {
/** @var Node\AttributeGroup[] PHP attribute groups */
public $attrGroups;
/** @var int Modifiers */
public $flags;
/** @var (Node\Arg|Node\VariadicPlaceholder)[] Arguments */
public $args;
/** @var null|Node\Name Name of extended class */
@ -36,11 +38,12 @@ class PrintableNewAnonClassNode extends Expr {
* @param array<string, mixed> $attributes Attributes
*/
public function __construct(
array $attrGroups, array $args, ?Node\Name $extends, array $implements,
array $attrGroups, int $flags, array $args, ?Node\Name $extends, array $implements,
array $stmts, array $attributes
) {
parent::__construct($attributes);
$this->attrGroups = $attrGroups;
$this->flags = $flags;
$this->args = $args;
$this->extends = $extends;
$this->implements = $implements;
@ -53,7 +56,7 @@ class PrintableNewAnonClassNode extends Expr {
// We don't assert that $class->name is null here, to allow consumers to assign unique names
// to anonymous classes for their own purposes. We simplify ignore the name here.
return new self(
$class->attrGroups, $newNode->args, $class->extends, $class->implements,
$class->attrGroups, $class->flags, $newNode->args, $class->extends, $class->implements,
$class->stmts, $newNode->getAttributes()
);
}
@ -63,6 +66,6 @@ class PrintableNewAnonClassNode extends Expr {
}
public function getSubNodeNames(): array {
return ['attrGroups', 'args', 'extends', 'implements', 'stmts'];
return ['attrGroups', 'flags', 'args', 'extends', 'implements', 'stmts'];
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1633,6 +1633,7 @@ abstract class PrettyPrinterAbstract implements PrettyPrinter {
Stmt\ClassMethod::class . '->flags' => ['pModifiers', \T_FUNCTION],
Stmt\Class_::class . '->flags' => ['pModifiers', \T_CLASS],
Stmt\Property::class . '->flags' => ['pModifiers', \T_VARIABLE],
PrintableNewAnonClassNode::class . '->flags' => ['pModifiers', \T_CLASS],
Param::class . '->flags' => ['pModifiers', \T_VARIABLE],
Expr\Closure::class . '->static' => ['pStatic', \T_FUNCTION],
Expr\ArrowFunction::class . '->static' => ['pStatic', \T_FN],

View File

@ -210,6 +210,7 @@ use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Scalar;
use PhpParser\Node\Stmt;
use PhpParser\Modifiers;
\$fn = function(&\$stmts) { $modification };
CODE
);

View File

@ -55,3 +55,14 @@ function test(
public T3 $z
= 'x',
) {}
-----
<?php
new class {};
new readonly class {};
-----
$stmts[0]->expr->class->flags = Modifiers::READONLY;
$stmts[1]->expr->class->flags = 0;
-----
<?php
readonly class {};
class {};

View File

@ -0,0 +1,25 @@
Readonly anonymous class
-----
<?php
new readonly class {};
-----
array(
0: Stmt_Expression(
expr: Expr_New(
class: Stmt_Class(
attrGroups: array(
)
flags: READONLY (64)
name: null
extends: null
implements: array(
)
stmts: array(
)
)
args: array(
)
)
)
)

View File

@ -10,6 +10,7 @@ new class($a) extends A {
$this->a = $a;
}
};
new readonly class {};
-----
new class
{
@ -25,3 +26,6 @@ new class($a) extends A
$this->a = $a;
}
};
new readonly class
{
};