fix(php): 修复$this变量重新赋值检查并添加类功能测试

- 添加对$this变量重新赋值的错误检查,防止Cannot re-assign $this错误
- 新增destructor异常处理测试用例验证析构函数中的异常捕获
- 添加工厂模式测试用例验证对象创建功能
- 新增final方法测试用例验证最终方法重写规则
- 添加abstract与final冲突测试用例验证编译时错误处理
- 新增__toString与__destruct交互测试用例验证字符串转换功能
pull/1/head
韩天峰 7 months ago
parent a6826d5fd0
commit 66249916f5
  1. 3
      src/Php/CompilerBase.php
  2. 57
      tests/core/classes/destructor_and_exceptions.phpt
  3. 33
      tests/core/classes/factory_001.phpt
  4. 30
      tests/core/classes/final.phpt
  5. 16
      tests/core/classes/final_abstract.phpt
  6. 26
      tests/core/classes/tostring_002.phpt

@ -775,6 +775,9 @@ class CompilerBase extends \PhpAot\Core\Translator
return $code . '}';
}
$var = $this->parseIdentifier($left);
if ($var === 'this_') {
$this->fatalError($left, 'Cannot re-assign $this');
}
$expr = $this->parseExpr($right);
if (!$this->hasVar($var)) {

@ -0,0 +1,57 @@
--TEST--
ZE2 catch exception thrown in destructor
--FILE--
<?php
class FailClass
{
public $fatal;
function __destruct()
{
echo __METHOD__ . "\n";
throw new exception("FailClass");
echo "Done: " . __METHOD__ . "\n";
}
}
class FatalException extends Exception
{
function __construct($what)
{
echo __METHOD__ . "\n";
$o = new FailClass;
unset($o);
echo "Done: " . __METHOD__ . "\n";
}
}
function main() {
try
{
$a = new FailClass;
unset($a);
}
catch(Exception $e)
{
echo "Caught: " . $e->getMessage() . "\n";
}
try
{
throw new FatalException("Damn");
}
catch(Exception $e)
{
echo "Caught Exception: " . $e->getMessage() . "\n";
}
catch(FatalException $e)
{
echo "Caught FatalException: " . $e->getMessage() . "\n";
}
}
?>
--EXPECT--
FailClass::__destruct
Caught: FailClass
FatalException::__construct
FailClass::__destruct
Caught Exception: FailClass

@ -0,0 +1,33 @@
--TEST--
ZE2 factory objects
--FILE--
<?php
class Circle {
function draw() {
echo "Circle\n";
}
}
class Square {
function draw() {
print "Square\n";
}
}
function ShapeFactoryMethod($shape) {
switch ($shape) {
case "Circle":
return new Circle();
case "Square":
return new Square();
}
}
function main() {
ShapeFactoryMethod("Circle")->draw();
ShapeFactoryMethod("Square")->draw();
}
?>
--EXPECT--
Circle
Square

@ -0,0 +1,30 @@
--TEST--
ZE2 A method may be redeclared final
--FILE--
<?php
class first {
function show() {
echo "Call to function first::show()\n";
}
}
class second extends first {
final function show() {
echo "Call to function second::show()\n";
}
}
function main() {
$t = new first();
$t->show();
$t2 = new second();
$t2->show();
echo "Done\n";
}
?>
--EXPECT--
Call to function first::show()
Call to function second::show()
Done

@ -0,0 +1,16 @@
--TEST--
ZE2 A final method cannot be abstract
--SKIPIF--
<?php die('skip, failed at compile time'); ?>
--FILE--
<?php
class fail {
final abstract function show();
}
function main() {
echo "Done\n"; // Shouldn't be displayed
}
?>
--EXPECTF--
Fatal error: Cannot use the final modifier on an abstract method in %s on line %d

@ -0,0 +1,26 @@
--TEST--
ZE2 __toString() in __destruct
--FILE--
<?php
class Test
{
function __toString(): string
{
return "Hello\n";
}
function __destruct()
{
echo $this;
}
}
function main() {
$o = new Test;
$o = new Test;
}
?>
--EXPECT--
Hello
Hello
Loading…
Cancel
Save