feat(php): 添加对 trait 魔术常量 __TRAIT__ 的支持

- 在 CompilerBase 中添加 Scalar_MagicConst_Trait 的解析支持
- 为 __TRAIT__ 常量实现作用域检查逻辑
- 为 __CLASS__ 常量添加 trait 环境下的返回逻辑
- 在 Preprocessor 中添加类属性钩子不支持的错误提示
- 添加 trait 魔术常量的功能测试用例
- 更新 trait 示例代码以展示魔术常量使用
pull/1/head
韩天峰 4 months ago
parent 37bfc24432
commit 5bf12a10ed
  1. 24
      examples/property-hook.php
  2. 5
      examples/trait.php
  3. 12
      src/Php/CompilerBase.php
  4. 3
      src/Php/Preprocessor.php
  5. 28
      tests/aot/trait/magic-const.phpt

@ -0,0 +1,24 @@
<?php
class Example
{
private bool $modified = false;
public string $foo = 'default value' {
get {
if ($this->modified) {
return $this->foo . ' (modified)';
}
return $this->foo;
}
set(string $value) {
$this->foo = strtolower($value);
$this->modified = true;
}
}
}
function main()
{
$example = new Example();
$example->foo = 'Hello World';
}

@ -3,6 +3,8 @@
trait TraitA { trait TraitA {
public function sayHello() { public function sayHello() {
echo 'Hello'; echo 'Hello';
var_dump(__TRAIT__);
var_dump(__CLASS__);
} }
} }
@ -24,5 +26,8 @@ class MyHelloWorld
} }
} }
function main()
{
$obj = new MyHelloWorld(); $obj = new MyHelloWorld();
$obj->sayHelloWorld(); $obj->sayHelloWorld();
}

@ -478,6 +478,7 @@ class CompilerBase extends \PhpAot\Core\Translator
case 'Scalar_MagicConst_Function': case 'Scalar_MagicConst_Function':
case 'Scalar_MagicConst_Method': case 'Scalar_MagicConst_Method':
case 'Scalar_MagicConst_Class': case 'Scalar_MagicConst_Class':
case 'Scalar_MagicConst_Trait':
return $this->parseMagicConst($expr); return $this->parseMagicConst($expr);
case 'Scalar_InterpolatedString': case 'Scalar_InterpolatedString':
return $this->parseInterpolatedString($expr); return $this->parseInterpolatedString($expr);
@ -3472,6 +3473,17 @@ class CompilerBase extends \PhpAot\Core\Translator
case 'Scalar_MagicConst_Function': case 'Scalar_MagicConst_Function':
return '"' . $this->escapeString($function) . '"'; return '"' . $this->escapeString($function) . '"';
case 'Scalar_MagicConst_Class': case 'Scalar_MagicConst_Class':
if (!$this->classDef) {
$this->fatalError($expr, 'The magic constant `__CLASS__` is not allowed in global scope');
}
if ($this->classDef->trait) {
return Symbol::getCalledClass();
}
return '"' . $this->escapeString($class) . '"';
case 'Scalar_MagicConst_Trait':
if (!$this->classDef or !$this->classDef->trait) {
$this->fatalError($expr, 'The magic constant `__TRAIT__` is not allowed in global scope');
}
return '"' . $this->escapeString($class) . '"'; return '"' . $this->escapeString($class) . '"';
case 'Scalar_MagicConst_Method': case 'Scalar_MagicConst_Method':
return '"' . $this->escapeString($class) . '::' . $this->escapeString($this->method) . '"'; return '"' . $this->escapeString($class) . '::' . $this->escapeString($this->method) . '"';

@ -546,6 +546,9 @@ class Preprocessor extends CompilerBase
protected function parseClassPropertyDef(Node\Stmt\Property $v): void protected function parseClassPropertyDef(Node\Stmt\Property $v): void
{ {
if ($v->hooks and count($v->hooks) > 0) {
$this->fatalError($v, 'The class property hooks are not supported');
}
$oriCtx = $this->context; $oriCtx = $this->context;
$this->context = $this->classDef->propertyContext; $this->context = $this->classDef->propertyContext;
$flags = $this->parseModifiers($v->flags); $flags = $this->parseModifiers($v->flags);

@ -0,0 +1,28 @@
--TEST--
trait full class name
--FILE--
<?php
trait TraitA {
public function sayHello() {
var_dump(__TRAIT__);
var_dump(__CLASS__);
}
}
class MyHelloWorld
{
use TraitA;
public function sayHelloWorld() {
$this->sayHello();
}
}
function main()
{
$obj = new MyHelloWorld();
$obj->sayHelloWorld();
}
?>
--EXPECT--
string(6) "TraitA"
string(12) "MyHelloWorld"
Loading…
Cancel
Save