TypePHP 编译器
https://swoole.com/aot/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
96 lines
2.8 KiB
96 lines
2.8 KiB
<?php
|
|
/**
|
|
* This file is part of TypePHP.
|
|
*
|
|
* @link https://www.swoole.com/
|
|
* @contact service@swoole.com
|
|
*/
|
|
|
|
namespace TypePhp\Transform;
|
|
|
|
use Closure;
|
|
use PhpParser\Node;
|
|
use PhpParser\NodeVisitorAbstract;
|
|
use TypePhp\Exception\SyntaxError;
|
|
|
|
/**
|
|
* Applies the allow_dynamic values used by php-src at each declaration site.
|
|
*
|
|
* false: class constants, property defaults and enum cases.
|
|
* true: attributes, parameter defaults and global constants.
|
|
*
|
|
* PHP 8.4+ compiles static variable initializers as regular expressions and
|
|
* evaluates them only once, so they do not use the constant-expression path.
|
|
*/
|
|
final class ConstantExpressionValidationVisitor extends NodeVisitorAbstract
|
|
{
|
|
private readonly ConstantExpressionValidator $validator;
|
|
|
|
/** @param null|Closure(Node, string): never $fatalError */
|
|
public function __construct(
|
|
string $phpVersion,
|
|
private readonly ?Closure $fatalError = null,
|
|
)
|
|
{
|
|
$this->validator = new ConstantExpressionValidator($phpVersion);
|
|
}
|
|
|
|
public function enterNode(Node $node): null
|
|
{
|
|
try {
|
|
return $this->validateNode($node);
|
|
} catch (SyntaxError $error) {
|
|
if ($this->fatalError !== null) {
|
|
($this->fatalError)($node, $error->getMessage());
|
|
}
|
|
throw $error;
|
|
}
|
|
}
|
|
|
|
private function validateNode(Node $node): null
|
|
{
|
|
if ($node instanceof Node\Attribute) {
|
|
$this->validator->validateArguments(
|
|
$node->args,
|
|
allowDynamic: true,
|
|
attributeArgumentList: true,
|
|
);
|
|
return null;
|
|
}
|
|
|
|
if ($node instanceof Node\Stmt\ClassConst) {
|
|
foreach ($node->consts as $constant) {
|
|
$this->validator->validate($constant->value, allowDynamic: false);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
if ($node instanceof Node\Stmt\Property) {
|
|
foreach ($node->props as $property) {
|
|
if ($property->default !== null) {
|
|
$this->validator->validate($property->default, allowDynamic: false);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
if ($node instanceof Node\Stmt\EnumCase && $node->expr !== null) {
|
|
$this->validator->validate($node->expr, allowDynamic: false);
|
|
return null;
|
|
}
|
|
|
|
if ($node instanceof Node\Param && $node->default !== null) {
|
|
$this->validator->validate($node->default, allowDynamic: true);
|
|
return null;
|
|
}
|
|
|
|
if ($node instanceof Node\Stmt\Const_) {
|
|
foreach ($node->consts as $constant) {
|
|
$this->validator->validate($constant->value, allowDynamic: true);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|