From 35117d5c1437a12b2c0fb5035c8df9c61de0e136 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Fri, 27 Feb 2026 19:14:26 +0800 Subject: [PATCH] =?UTF-8?q?feat(compiler):=20=E6=B7=BB=E5=8A=A0=E6=9E=84?= =?UTF-8?q?=E9=80=A0=E6=96=B9=E6=B3=95=E5=B1=9E=E6=80=A7=E6=8F=90=E5=8D=87?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 ArgInfo 中添加 property 属性标识参数是否为属性提升 - 引入 PropertyPromotion trait 处理属性提升代码生成 - 在编译器中实现构造方法属性提升的解析和代码生成逻辑 - 支持将 promoted 参数转换为类属性定义 - 生成对应的 this_.setProperty 调用代码 - 更新函数信息解析以处理属性提升参数 --- bin/gen_stub.php | 21 +++++++++++++++++---- src/Php/ArgInfo.php | 1 + src/Php/CompilerBase.php | 19 +++++++++++++++++++ src/Php/Generator/PropertyPromotion.php | 16 ++++++++++++++++ 4 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 src/Php/Generator/PropertyPromotion.php diff --git a/bin/gen_stub.php b/bin/gen_stub.php index 4f724d4a..fe1fc7d4 100755 --- a/bin/gen_stub.php +++ b/bin/gen_stub.php @@ -81,7 +81,6 @@ function processStubFile(string $stubFile, Context $context, bool $includeOnly = global $translator; $stubFilenameWithoutExtension = $translator->getArgInfoStubFilename($stubFile); $arginfoFile = $context->objectFile; - var_dump($arginfoFile); $legacyFile = "{$stubFilenameWithoutExtension}_legacy_arginfo.h"; $stubCode = file_get_contents($stubFile); @@ -4502,7 +4501,8 @@ class FileInfo { $classStmt, $cond, $this->isUndocumentable, - $this->getMinimumPhpVersionIdCompatibility() + $this->getMinimumPhpVersionIdCompatibility(), + $propertyInfos, ); } else if ($classStmt instanceof Stmt\EnumCase) { $enumCaseInfos[] = new EnumCaseInfo( @@ -4738,7 +4738,8 @@ function parseFunctionLike( Node\FunctionLike $func, ?string $cond, bool $isUndocumentable, - ?int $minimumPhpVersionIdCompatibility + ?int $minimumPhpVersionIdCompatibility, + ?array &$propertyInfos = null, ): FuncInfo { try { $comments = $func->getComments(); @@ -4810,7 +4811,19 @@ function parseFunctionLike( $foundVariadic = false; foreach ($func->getParams() as $i => $param) { if ($param->isPromoted()) { - throw new Exception("Promoted properties are not supported"); + $propertyItem = new Stmt\PropertyProperty($param->var->name, $param->default); + $property = new Stmt\Property($param->flags, [$propertyItem], $param->getAttributes(), $param->type, $param->attrGroups); + $propertyInfos[] = parseProperty( + $name->className, + $classFlags, + $param->flags, + $propertyItem, + $property->type, + $property->getComments(), + $prettyPrinter, + $minimumPhpVersionIdCompatibility, + AttributeInfo::createFromGroups($property->attrGroups) + ); } $varName = $param->var->name; diff --git a/src/Php/ArgInfo.php b/src/Php/ArgInfo.php index badfde5e..f2ba9e6a 100644 --- a/src/Php/ArgInfo.php +++ b/src/Php/ArgInfo.php @@ -15,4 +15,5 @@ class ArgInfo public string $default = ''; public bool $byRef = false; public bool $variadic = false; + public bool $property = false; } diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index a3128acc..538417dc 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -19,6 +19,7 @@ use PhpAot\Php\Exception\Redo; use PhpAot\Php\Exception\Skip; use PhpAot\Php\Generator\ClosureGenerator; use PhpAot\Php\Generator\PlaceHolderGenerator; +use PhpAot\Php\Generator\PropertyPromotion; use PhpAot\Php\Generator\Utils; use PhpParser\Modifiers; use PhpParser\Node; @@ -39,6 +40,7 @@ class CompilerBase extends \PhpAot\Core\Translator use FuncCallOptimizer; use ClosureGenerator; use PlaceHolderGenerator; + use PropertyPromotion; use Utils; public const string TYPE_VAR = 'php::Var'; @@ -831,6 +833,13 @@ class CompilerBase extends \PhpAot\Core\Translator $this->indentLevel++; $code .= $this->genLocalVarDecl(); $code .= "\n"; + // Constructor Property Promotion + foreach ($this->functionDef->argInfoList as $argInfo) { + if (!$argInfo->property) { + continue; + } + $code .= $this->genPropertyPromotion($argInfo); + } $this->indentLevel--; $code .= $this->genDebugInfo(); $code .= $stmts; @@ -924,6 +933,15 @@ class CompilerBase extends \PhpAot\Core\Translator if ($this->stubFile and !$param->type) { throw new \RuntimeException('No type for ' . $this->parseIdentifier($param->var)); } + // 构造方法属性定义语法(Constructor Property Promotion) + if ($param->isPromoted()) { + if (!$this->classDef or !$this->methodDef or $this->methodDef->name !== '__construct') { + $this->fatalError($param, 'Promoted properties are not supported'); + } + $name = $this->parseIdentifier($param->var); + $propertyDef = new PropertyDef($name, $param->flags, $param->type, $param->default); + $this->classDef->properties[$name] = $propertyDef; + } if ($param->variadic and $i !== $last) { $this->fatalError($param, 'Variadic parameters must be the last parameter'); } @@ -939,6 +957,7 @@ class CompilerBase extends \PhpAot\Core\Translator $argInfo->type = $type; $argInfo->byRef = $param->byRef; $argInfo->variadic = $param->variadic; + $argInfo->property = $param->isPromoted(); if (isset($param->default)) { $functionDef->argCountRequired = count($list) - 1; /** diff --git a/src/Php/Generator/PropertyPromotion.php b/src/Php/Generator/PropertyPromotion.php new file mode 100644 index 00000000..06de8457 --- /dev/null +++ b/src/Php/Generator/PropertyPromotion.php @@ -0,0 +1,16 @@ +genCharPtr($argInfo->name) . ", " . $argInfo->name . ")"; + $code .= ";\n"; + return $code; + } +} \ No newline at end of file