test(anonymous): 添加匿名类相关测试用例

- 新增 001.phpt 测试基础匿名类声明功能
- 新增 002.phpt 测试匿名类继承和实现接口功能
- 新增 003.phpt 测试匿名类重复使用场景
- 新增 004.phpt 测试匿名类继承机制
- 修改编译器基类中类名获取逻辑,支持反斜杠开头的命名空间类名
- 修复函数中声明类的错误检查逻辑
- 改进变量检测逻辑以避免未定义变量错误
- 修复类定义代码中的数组初始化逻辑
- 为类名添加反斜杠前缀以确保正确引用
- 添加静态调用注释以改善调试信息
- 调整枚举测试文件中函数位置以符合预期结构
pull/1/head
韩天峰 7 months ago
parent 8ec0723ed5
commit 35a81376a1
  1. 11
      src/Php/CompilerBase.php
  2. 12
      tests/aot/enum2.phpt
  3. 11
      tests/zend/anon/001.phpt
  4. 22
      tests/zend/anon/002.phpt
  5. 55
      tests/zend/anon/003.phpt
  6. 33
      tests/zend/anon/004.phpt

@ -593,6 +593,10 @@ class CompilerBase extends \PhpAot\Core\Translator
protected function getNamespacedClassName(string $class): string
{
if ($class[0] === '\\') {
return $class;
}
$ns2 = explode('\\', trim($class, '\\'));
if (isset($this->useAliases[$ns2[0]])) {
@ -971,7 +975,6 @@ class CompilerBase extends \PhpAot\Core\Translator
break;
case 'Stmt_Class':
$this->fatalError($v, 'Cannot declare class in function');
break;
default:
abort($v);
}
@ -1980,7 +1983,7 @@ class CompilerBase extends \PhpAot\Core\Translator
}
} elseif ($this->isArrayDimFetch($arg->value)) {
$array = $this->parseIdentifier($arg->value->var);
if (!$this->hasVar($array)) {
if ($this->isVarExpr($arg->value->var) and !$this->hasVar($array)) {
$this->fatalError($arg, 'Undefined variable `$' . $array . '`');
}
if ($funcName and Reflection::isReferenceArg($funcName, $i)) {
@ -2354,6 +2357,7 @@ class CompilerBase extends \PhpAot\Core\Translator
$out .= "\n\t";
}
}
$out .= '0,';
return $out;
}
@ -2375,6 +2379,7 @@ class CompilerBase extends \PhpAot\Core\Translator
$this->addConstData($className . '_code', $classCode);
$this->beforeStmtLines[] = 'if (!' . $className . '_defined) {'
. $className . '_defined = true; php::eval((const char *)' . $className . '_code);}';
$className = '\\' . $className;
} else {
$this->fatalError($expr, 'must be anonymous class');
}
@ -3161,6 +3166,8 @@ class CompilerBase extends \PhpAot\Core\Translator
return $this->parseParentMethodCall($expr);
}
$this->beforeStmtLines[] = '// Static Call: ' . $class . '::' . $method;
if ($this->isNameExpr($expr->class) and $this->isIdExpr($expr->name)) {
$nativeFunc = $this->getNativeStaticMethod($class, $method);
if ($nativeFunc) {

@ -2,14 +2,14 @@
enum 2
--FILE--
<?php
enum TestEnum2: int {
case Hearts = 2;
case Diamonds = 1;
case Clubs = 4;
case Spades = 3;
}
function main()
{
enum TestEnum2: int {
case Hearts = 2;
case Diamonds = 1;
case Clubs = 4;
case Spades = 3;
}
var_dump(TestEnum2::cases());
}
?>

@ -0,0 +1,11 @@
--TEST--
declare bare anonymous class
--FILE--
<?php
function main() {
var_dump(new class{});
}
?>
--EXPECTF--
object(%s)#%d (0) {
}

@ -0,0 +1,22 @@
--TEST--
declare anonymous class extending another
--FILE--
<?php
class A{}
interface B{
public function method();
}
function main() {
$a = new class extends A implements B {
public function method(){
return true;
}
};
var_dump($a instanceof A, $a instanceof B);
}
?>
--EXPECT--
bool(true)
bool(true)

@ -0,0 +1,55 @@
--TEST--
reusing anonymous classes
--FILE--
<?php
$i = 0;
while ($i++<10) {
var_dump(new class($i) {
public $i;
public function __construct($i) {
$this->i = $i;
}
});
}
?>
--EXPECTF--
object(%s)#1 (1) {
["i"]=>
int(1)
}
object(%s)#1 (1) {
["i"]=>
int(2)
}
object(%s)#1 (1) {
["i"]=>
int(3)
}
object(%s)#1 (1) {
["i"]=>
int(4)
}
object(%s)#1 (1) {
["i"]=>
int(5)
}
object(%s)#1 (1) {
["i"]=>
int(6)
}
object(%s)#1 (1) {
["i"]=>
int(7)
}
object(%s)#1 (1) {
["i"]=>
int(8)
}
object(%s)#1 (1) {
["i"]=>
int(9)
}
object(%s)#1 (1) {
["i"]=>
int(10)
}

@ -0,0 +1,33 @@
--TEST--
testing anonymous inheritance
--FILE--
<?php
class Outer {
protected $data;
public function __construct($data) {
$this->data = $data;
}
public function getArrayAccess() {
/* create a proxy object implementing array access */
return new class($this->data) extends Outer implements ArrayAccess {
public function offsetGet($offset): mixed { return $this->data[$offset]; }
public function offsetSet($offset, $data): void { $this->data[$offset] = $data; }
public function offsetUnset($offset): void { unset($this->data[$offset]); }
public function offsetExists($offset): bool { return isset($this->data[$offset]); }
};
}
}
function main() {
$outer = new Outer(array(
rand(1, 100)
));
/* not null because inheritance */
var_dump($outer->getArrayAccess()[0]);
}
?>
--EXPECTF--
int(%d)
Loading…
Cancel
Save