feat(parser): add support for promoted constructor properties

- Add isPromoted property to PropertyInfo class
- Include isPromoted flag in PropertyInfo constructor and initialization
- Set ZEND_ACC_PROMOTED flag for promoted properties in PHP 8.0+
- Update Preprocessor to track promoted status during property creation
- Add promoted flag to PropertyDef entity
- Remove xfails for promoted property tests since they now pass
- Handle promoted properties in constructor parameter processing
pull/16/head
韩天峰 2 months ago
parent 852709af96
commit 330d7eb655
  1. 1
      src/Entity/PropertyDef.php
  2. 5
      src/Preprocessor.php
  3. 14
      src/gen_stub.php
  4. 2
      tests/aot/symfony/sensitive-promoted-readonly.phpt

@ -21,6 +21,7 @@ class PropertyDef
public string $class = '';
public array $typeCheck = [];
public string $typeStr = '';
public bool $promoted = false;
public function __construct(string $name, int $flags, string $type, ?string $default = null, bool $nullable = false)
{

@ -324,7 +324,7 @@ class Preprocessor extends CompilerBase
// Promoted property defaults belong to the constructor parameter,
// not to the property default table. The property itself must stay
// uninitialized until __construct assigns it.
$this->addClassProperty($phpName, $param->flags, $param->type, null, $nullable, $param);
$this->addClassProperty($phpName, $param->flags, $param->type, null, $nullable, $param, true);
}
if ($param->variadic) {
if ($i !== $last) {
@ -676,7 +676,7 @@ class Preprocessor extends CompilerBase
* Create and register a class property with type normalization, shared by
* regular property declarations and constructor property promotion.
*/
protected function addClassProperty(string $name, int $flags, ?NodeAbstract $typeNode, $defaultNode, bool $nullable, NodeAbstract $errorNode): PropertyDef
protected function addClassProperty(string $name, int $flags, ?NodeAbstract $typeNode, $defaultNode, bool $nullable, NodeAbstract $errorNode, bool $promoted = false): PropertyDef
{
$flags = $this->parseModifiers($flags);
$class = '';
@ -701,6 +701,7 @@ class Preprocessor extends CompilerBase
$propDef = new PropertyDef($name, $flags, $type, $default, $nullable);
$propDef->class = $class;
$propDef->arrayInitPlan = $arrayInitPlan;
$propDef->promoted = $promoted;
if ($typeNode instanceof NullableType || $typeNode instanceof UnionType || $typeNode instanceof IntersectionType) {
$typeInfo = $this->buildTypeCheckFromNode($typeNode);
$propDef->typeCheck = $typeInfo['check'];

@ -3202,6 +3202,7 @@ class PropertyInfo extends VariableLike
private /* readonly */ ?string $defaultValueString;
private /* readonly */ bool $isDocReadonly;
private /* readonly */ bool $isVirtual;
private /* readonly */ bool $isPromoted;
/**
* @param AttributeInfo[] $attributes
@ -3216,6 +3217,7 @@ class PropertyInfo extends VariableLike
?string $defaultValueString,
bool $isDocReadonly,
bool $isVirtual,
bool $isPromoted,
?string $link,
?int $phpVersionIdMinimumCompatibility,
array $attributes,
@ -3227,6 +3229,7 @@ class PropertyInfo extends VariableLike
$this->defaultValueString = $defaultValueString;
$this->isDocReadonly = $isDocReadonly;
$this->isVirtual = $isVirtual;
$this->isPromoted = $isPromoted;
parent::__construct($flags, $type, $phpDocType, $link, $phpVersionIdMinimumCompatibility, $attributes, $exposedDocComment);
}
@ -3364,6 +3367,10 @@ class PropertyInfo extends VariableLike
$flags->addForVersionsAbove("ZEND_ACC_VIRTUAL", PHP_84_VERSION_ID);
}
if ($this->isPromoted) {
$flags->addForVersionsAbove("ZEND_ACC_PROMOTED", PHP_80_VERSION_ID);
}
return $flags;
}
@ -4972,7 +4979,8 @@ function parseFunctionLike(
$property->getComments(),
$prettyPrinter,
$minimumPhpVersionIdCompatibility,
AttributeInfo::createFromGroups($property->attrGroups)
AttributeInfo::createFromGroups($property->attrGroups),
true
);
}
@ -5186,7 +5194,8 @@ function parseProperty(
array $comments,
PrettyPrinterAbstract $prettyPrinter,
?int $phpVersionIdMinimumCompatibility,
array $attributes
array $attributes,
bool $isPromoted = false
): PropertyInfo {
$phpDocType = null;
@ -5228,6 +5237,7 @@ function parseProperty(
$property->default ? $prettyPrinter->prettyPrintExpr($property->default) : null,
$isDocReadonly,
$isVirtual,
$isPromoted,
$link,
$phpVersionIdMinimumCompatibility,
$attributes,

@ -1,7 +1,5 @@
--TEST--
Symfony pattern: SensitiveParameter attribute on promoted readonly constructor parameter
--XFAIL--
Known AOT bug: ReflectionProperty::isPromoted() is false for promoted constructor properties.
--FILE--
<?php

Loading…
Cancel
Save