refactor(php): 重构静态属性获取解析逻辑

- 将 findNativeStaticProperty 方法重命名为 resolveNativeStaticPropertyFetch 并返回对象
- 引入 StaticPropertyFetchResolution 类来封装静态属性获取的结果
- 修改条件判断从 if ($native) 到 if ($native !== null) 以明确检查 null 值
- 更新 parseNativeStaticPropertyFetch 方法的返回类型为 ?string
- 优化静态属性引用变量的生成逻辑,使用解析结果中的类名
- 移除不再使用的 $class 参数并简化方法调用
- 添加新的解析器相关类文件以支持属性访问解析功能
pull/4/head
韩天峰 2 months ago
parent 6f15c61720
commit f631b395fc
  1. 38
      src/Php/CompilerBase.php
  2. 2
      src/Php/Parser/AssignOpTrait.php
  3. 31
      src/Php/Resolver/NativePropertyAccess.php
  4. 21
      src/Php/Resolver/PropertyAccessContext.php
  5. 66
      src/Php/Resolver/PropertyAssignTypeInfo.php
  6. 19
      src/Php/Resolver/StaticPropertyFetchResolution.php

@ -48,6 +48,7 @@ use PhpAot\Php\Resolver\NativePropertyAccess;
use PhpAot\Php\Resolver\PropertyAccessResult; use PhpAot\Php\Resolver\PropertyAccessResult;
use PhpAot\Php\Resolver\PropertyAccessResolver; use PhpAot\Php\Resolver\PropertyAccessResolver;
use PhpAot\Php\Resolver\PropertyAssignTypeInfo; use PhpAot\Php\Resolver\PropertyAssignTypeInfo;
use PhpAot\Php\Resolver\StaticPropertyFetchResolution;
use PhpParser\Modifiers; use PhpParser\Modifiers;
use PhpParser\Node; use PhpParser\Node;
use PhpParser\Node\ArrayItem; use PhpParser\Node\ArrayItem;
@ -2422,8 +2423,7 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont
case 'Expr_StaticPropertyFetch': case 'Expr_StaticPropertyFetch':
if ($this->isIdExpr($expr->name)) { if ($this->isIdExpr($expr->name)) {
if (!$this->getNativePropertyDef($expr)) { if (!$this->getNativePropertyDef($expr)) {
$class = null; $this->resolveNativeStaticPropertyFetch($expr);
$this->findNativeStaticProperty($expr, $class);
} }
$def = $this->getNativePropertyDef($expr); $def = $this->getNativePropertyDef($expr);
if ($def) { if ($def) {
@ -3880,7 +3880,7 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont
} }
if ($this->isStaticPropertyFetch($expr->var)) { if ($this->isStaticPropertyFetch($expr->var)) {
$native = $this->parseNativeStaticPropertyFetch($expr->var); $native = $this->parseNativeStaticPropertyFetch($expr->var);
if ($native) { if ($native !== null) {
return $native . str_repeat($op, 2); return $native . str_repeat($op, 2);
} }
@ -5781,7 +5781,7 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont
} }
} }
protected function findNativeStaticProperty(Expr\StaticPropertyFetch $expr, ?string &$class): ?string protected function resolveNativeStaticPropertyFetch(Expr\StaticPropertyFetch $expr): ?StaticPropertyFetchResolution
{ {
if ($this->isNameExpr($expr->class) and $this->isIdExpr($expr->name)) { if ($this->isNameExpr($expr->class) and $this->isIdExpr($expr->name)) {
$class = $this->parseIdentifier($expr->class); $class = $this->parseIdentifier($expr->class);
@ -5791,7 +5791,8 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont
} }
if ($class === 'self') { if ($class === 'self') {
if ($this->classDef->trait) { if ($this->classDef->trait) {
return Symbol::getStaticProperty() . '(' . Symbol::getCalledCe() . ', ' . $this->getLiteralString($propertyName) . ')'; $expression = Symbol::getStaticProperty() . '(' . Symbol::getCalledCe() . ', ' . $this->getLiteralString($propertyName) . ')';
return new StaticPropertyFetchResolution(null, $expression, false);
} }
$class = $this->getFullClassName(); $class = $this->getFullClassName();
} elseif ($class === 'parent') { } elseif ($class === 'parent') {
@ -5804,7 +5805,8 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont
} }
$result = $this->resolveNativeStaticProperty($expr, $propertyName, $class); $result = $this->resolveNativeStaticProperty($expr, $propertyName, $class);
if ($result !== null) { if ($result !== null) {
return $this->applyNativePropertyAccessResult($expr, $result); $expression = $this->applyNativePropertyAccessResult($expr, $result);
return new StaticPropertyFetchResolution($class, $expression, true);
} }
} }
return null; return null;
@ -5892,20 +5894,20 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont
return $expr->getAttribute('nativePropertyValueSource') === self::NATIVE_PROPERTY_VALUE_VAR; return $expr->getAttribute('nativePropertyValueSource') === self::NATIVE_PROPERTY_VALUE_VAR;
} }
protected function parseNativeStaticPropertyFetch(Expr\StaticPropertyFetch $expr): string|bool protected function parseNativeStaticPropertyFetch(Expr\StaticPropertyFetch $expr): ?string
{ {
$class = null; $resolution = $this->resolveNativeStaticPropertyFetch($expr);
$nativeProp = $this->findNativeStaticProperty($expr, $class); if ($resolution !== null) {
if ($nativeProp) { $nativeProp = $resolution->expression;
$def = $this->getNativePropertyDef($expr); $def = $this->getNativePropertyDef($expr);
if ($this->nativeTypes && $def) { if ($this->nativeTypes && $def && $resolution->class !== null) {
$info = $this->getHoistedObjectPropInfo($def->type); $info = $this->getHoistedObjectPropInfo($def->type);
$propName = $this->parseIdentifier($expr->name); $propName = $this->parseIdentifier($expr->name);
$refVar = '_static_' . str_replace('\\', '_', $class) . '_' . $propName; $refVar = '_static_' . str_replace('\\', '_', $resolution->class) . '_' . $propName;
if ($info['kind'] === 'zval') { if ($info['kind'] === 'zval') {
if (!isset($this->context->staticPropRefs[$refVar])) { if (!isset($this->context->staticPropRefs[$refVar])) {
$classPtr = $this->getClassEntryPtr($class); $classPtr = $this->getClassEntryPtr($resolution->class);
$this->context->staticPropRefs[$refVar] = [ $this->context->staticPropRefs[$refVar] = [
'type' => $info['type'], 'type' => $info['type'],
'classPtr' => $classPtr, 'classPtr' => $classPtr,
@ -5919,7 +5921,7 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont
} }
if (!isset($this->context->staticPropRefs[$refVar])) { if (!isset($this->context->staticPropRefs[$refVar])) {
$classPtr = $this->getClassEntryPtr($class); $classPtr = $this->getClassEntryPtr($resolution->class);
$this->context->staticPropRefs[$refVar] = [ $this->context->staticPropRefs[$refVar] = [
'type' => $info['type'], 'type' => $info['type'],
'classPtr' => $classPtr, 'classPtr' => $classPtr,
@ -5931,8 +5933,8 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont
return $refVar; return $refVar;
} }
if ($this->isNativePropertyAccess($expr)) { if ($resolution->nativeProperty && $resolution->class !== null) {
$classPtr = $this->getClassEntryPtr($class); $classPtr = $this->getClassEntryPtr($resolution->class);
$this->setNativePropertyValueSource($expr, self::NATIVE_PROPERTY_VALUE_DYNAMIC); $this->setNativePropertyValueSource($expr, self::NATIVE_PROPERTY_VALUE_DYNAMIC);
return Symbol::getStaticProperty() . '(' . $classPtr . ', ' . $nativeProp . ')'; return Symbol::getStaticProperty() . '(' . $classPtr . ', ' . $nativeProp . ')';
} else { } else {
@ -5940,13 +5942,13 @@ class CompilerBase extends \PhpAot\Core\Translator implements PropertyAccessCont
return $nativeProp; return $nativeProp;
} }
} }
return false; return null;
} }
protected function parseStaticPropertyFetch(Expr\StaticPropertyFetch $expr): string protected function parseStaticPropertyFetch(Expr\StaticPropertyFetch $expr): string
{ {
$native = $this->parseNativeStaticPropertyFetch($expr); $native = $this->parseNativeStaticPropertyFetch($expr);
if ($native) { if ($native !== null) {
return $native; return $native;
} }
return Symbol::getStaticProperty() . '(' . $this->identifierToStr($expr->class) . ', ' . $this->identifierToStr($expr->name) . ')'; return Symbol::getStaticProperty() . '(' . $this->identifierToStr($expr->class) . ', ' . $this->identifierToStr($expr->name) . ')';

@ -86,7 +86,7 @@ trait AssignOpTrait
{ {
$value = $this->trimBrackets($this->parseExpr($right)); $value = $this->trimBrackets($this->parseExpr($right));
$native = $this->parseNativeStaticPropertyFetch($left); $native = $this->parseNativeStaticPropertyFetch($left);
if ($native) { if ($native !== null) {
return $native . ' = ' . $value; return $native . ' = ' . $value;
} }
$class = $this->identifierToStr($left->class); $class = $this->identifierToStr($left->class);

@ -0,0 +1,31 @@
<?php
/**
* This file is part of Swoole-Compiler(AOT).
*
* @link https://www.swoole.com/
* @contact service@swoole.com
*/
namespace PhpAot\Php\Resolver;
use PhpAot\Php\Entity\ClassDef;
use PhpAot\Php\Entity\PropertyDef;
final readonly class NativePropertyAccess
{
public function __construct(
public string $offset,
public PropertyAccessResult $resolution,
) {
}
public function getClassDef(): ClassDef
{
return $this->resolution->classDef;
}
public function getPropertyDef(): PropertyDef
{
return $this->resolution->propertyDef;
}
}

@ -0,0 +1,21 @@
<?php
/**
* This file is part of Swoole-Compiler(AOT).
*
* @link https://www.swoole.com/
* @contact service@swoole.com
*/
namespace PhpAot\Php\Resolver;
use PhpAot\Php\Entity\ClassDef;
use PhpParser\NodeAbstract;
interface PropertyAccessContext
{
public function getClassDef(string $name): ?ClassDef;
public function getParentClass(string $class): string;
public function fatalError(NodeAbstract $node, string $msg): never;
}

@ -0,0 +1,66 @@
<?php
/**
* This file is part of Swoole-Compiler(AOT).
*
* @link https://www.swoole.com/
* @contact service@swoole.com
*/
namespace PhpAot\Php\Resolver;
use PhpAot\Php\CompilerBase;
use PhpAot\Php\Entity\PropertyDef;
final class PropertyAssignTypeInfo
{
public function getFixedDefaultValue(PropertyDef $def): ?string
{
return match ($def->type) {
CompilerBase::TYPE_INT => $def->default ?? '0',
CompilerBase::TYPE_FLOAT => $def->default ?? '0.0',
CompilerBase::TYPE_BOOL => $def->default ?? 'false',
CompilerBase::TYPE_STR => $def->default ?? CompilerBase::TYPE_STR . '()',
CompilerBase::TYPE_ARRAY => $def->default ?? CompilerBase::TYPE_ARRAY . '{}',
default => null,
};
}
public function isFixed(PropertyDef $def): bool
{
return in_array($def->type, [
CompilerBase::TYPE_INT,
CompilerBase::TYPE_FLOAT,
CompilerBase::TYPE_BOOL,
CompilerBase::TYPE_STR,
CompilerBase::TYPE_ARRAY,
], true) && !$def->nullable;
}
public function getRuntimeTypeCheck(PropertyDef $def): array
{
if (!empty($def->typeCheck)) {
return $def->typeCheck;
}
if ($def->type !== CompilerBase::TYPE_OBJECT || $def->class === '') {
return [];
}
$check = [];
if ($def->nullable) {
$check[] = ['kind' => 'isNull'];
}
$check[] = ['kind' => 'instanceof', 'class' => $def->class];
return $check;
}
public function getTypeString(PropertyDef $def): string
{
if ($def->typeStr !== '') {
return $def->typeStr;
}
if ($def->class !== '') {
return ($def->nullable ? '?' : '') . $def->class;
}
return $def->type;
}
}

@ -0,0 +1,19 @@
<?php
/**
* This file is part of Swoole-Compiler(AOT).
*
* @link https://www.swoole.com/
* @contact service@swoole.com
*/
namespace PhpAot\Php\Resolver;
final readonly class StaticPropertyFetchResolution
{
public function __construct(
public ?string $class,
public string $expression,
public bool $nativeProperty,
) {
}
}
Loading…
Cancel
Save