- 添加对字面量除零、模零、赋值除零和赋值模零操作的编译时检查 - 实现对整数、浮点数和字符串类型的零值检测 - 为 AssignOpTrait 和 BinaryOpTrait 添加 guardLiteralDivisionByZero 方法 - 改进原生属性访问的类名解析,使用完整的类名进行查找 - 支持 static 关键字作为类名解析的一部分 - 添加 isSameClassName 和 isSameOrSubclassOf 辅助方法用于类继承关系判断 - 实现受保护属性访问权限控制的 canAccessProtectedProperty 方法 - 添加多个测试文件验证除零检查和原生属性访问功能 - 创建 NativePropertyTest 和 OperatorTest 测试类验证相关功能pull/2/head
parent
7e52d51b5b
commit
91675ed366
15 changed files with 271 additions and 15 deletions
@ -0,0 +1,7 @@ |
||||
<?php |
||||
|
||||
function main(): void |
||||
{ |
||||
$value = 10; |
||||
$value /= 0; |
||||
} |
||||
@ -0,0 +1,7 @@ |
||||
<?php |
||||
|
||||
function main(): void |
||||
{ |
||||
$value = 10; |
||||
$value %= 0; |
||||
} |
||||
@ -0,0 +1,6 @@ |
||||
<?php |
||||
|
||||
function main(): void |
||||
{ |
||||
var_dump(1.0 / 0.0); |
||||
} |
||||
@ -0,0 +1,6 @@ |
||||
<?php |
||||
|
||||
function main(): void |
||||
{ |
||||
var_dump(10 / 0); |
||||
} |
||||
@ -0,0 +1,6 @@ |
||||
<?php |
||||
|
||||
function main(): void |
||||
{ |
||||
var_dump(10 / '0.00'); |
||||
} |
||||
@ -0,0 +1,6 @@ |
||||
<?php |
||||
|
||||
function main(): void |
||||
{ |
||||
var_dump(10 % 0); |
||||
} |
||||
@ -0,0 +1,69 @@ |
||||
<?php |
||||
|
||||
namespace NativePropSource { |
||||
use native_types; |
||||
|
||||
class Target |
||||
{ |
||||
public static int $count = 1; |
||||
public int $value = 2; |
||||
protected int $protectedValue = 3; |
||||
} |
||||
} |
||||
|
||||
namespace NativePropSource\Target { |
||||
use native_types; |
||||
use NativePropSource\Target; |
||||
|
||||
class Child extends Target |
||||
{ |
||||
public function readThis(): int |
||||
{ |
||||
return $this->value; |
||||
} |
||||
|
||||
public function readInheritedProtected(Target $target): int |
||||
{ |
||||
return $target->protectedValue; |
||||
} |
||||
|
||||
public static function readSelf(): int |
||||
{ |
||||
return self::$count; |
||||
} |
||||
|
||||
public static function readStatic(): int |
||||
{ |
||||
return static::$count; |
||||
} |
||||
|
||||
public static function readParent(): int |
||||
{ |
||||
return parent::$count; |
||||
} |
||||
} |
||||
|
||||
function readObject(): int |
||||
{ |
||||
$target = new Target(); |
||||
return $target->value; |
||||
} |
||||
|
||||
function readStaticByUse(): int |
||||
{ |
||||
return Target::$count; |
||||
} |
||||
} |
||||
|
||||
namespace { |
||||
function main(): void |
||||
{ |
||||
$child = new \NativePropSource\Target\Child(); |
||||
var_dump($child->readThis()); |
||||
var_dump(\NativePropSource\Target\readObject()); |
||||
var_dump(\NativePropSource\Target\readStaticByUse()); |
||||
var_dump(\NativePropSource\Target\Child::readSelf()); |
||||
var_dump(\NativePropSource\Target\Child::readStatic()); |
||||
var_dump(\NativePropSource\Target\Child::readParent()); |
||||
} |
||||
} |
||||
@ -0,0 +1,20 @@ |
||||
<?php |
||||
|
||||
use native_types; |
||||
|
||||
class NativePrivateOwner |
||||
{ |
||||
private int $value = 1; |
||||
} |
||||
|
||||
class NativePrivateReader |
||||
{ |
||||
public function read(NativePrivateOwner $owner): int |
||||
{ |
||||
return $owner->value; |
||||
} |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
} |
||||
@ -0,0 +1,20 @@ |
||||
<?php |
||||
|
||||
use native_types; |
||||
|
||||
class NativeProtectedOwner |
||||
{ |
||||
protected int $value = 1; |
||||
} |
||||
|
||||
class NativeProtectedReader |
||||
{ |
||||
public function read(NativeProtectedOwner $owner): int |
||||
{ |
||||
return $owner->value; |
||||
} |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
} |
||||
@ -0,0 +1,40 @@ |
||||
<?php |
||||
|
||||
use PhpAot\Php\CompilerTest; |
||||
use PhpAot\Php\Exception\TestError; |
||||
|
||||
class NativePropertyTest extends \BaseTest |
||||
{ |
||||
private function compile(string $file): void |
||||
{ |
||||
global $translator; |
||||
|
||||
$compiler = CompilerTest::create(ROOT_PATH); |
||||
$translator = $compiler; |
||||
$testFile = __DIR__ . '/../code/' . $file; |
||||
$compiler->addFiles([$testFile]); |
||||
$compiler->prepareFile($testFile); |
||||
$compiler->convertFile($testFile); |
||||
|
||||
$this->addToAssertionCount(1); |
||||
} |
||||
|
||||
public function testFindNativePropertyUsesFullClassNameAcrossBranches(): void |
||||
{ |
||||
try { |
||||
$this->compile('native-property-full-name.php'); |
||||
} catch (TestError $e) { |
||||
$this->fail($e->getMessage()); |
||||
} |
||||
} |
||||
|
||||
public function testCannotAccessPrivateNativePropertyFromUnrelatedClass(): void |
||||
{ |
||||
$this->exec('Cannot access private property `value` of class `NativePrivateOwner`', 'native-property-private-other-class.php'); |
||||
} |
||||
|
||||
public function testCannotAccessProtectedNativePropertyFromUnrelatedClass(): void |
||||
{ |
||||
$this->exec('Cannot access protected property `value` of class `NativeProtectedOwner`', 'native-property-protected-unrelated-class.php'); |
||||
} |
||||
} |
||||
@ -0,0 +1,34 @@ |
||||
<?php |
||||
|
||||
class OperatorTest extends \BaseTest |
||||
{ |
||||
public function testLiteralIntDivideByZeroDoesNotCompile(): void |
||||
{ |
||||
$this->exec('Cannot divide or modulo by zero', 'divide-by-zero-int.php'); |
||||
} |
||||
|
||||
public function testLiteralFloatDivideByZeroDoesNotCompile(): void |
||||
{ |
||||
$this->exec('Cannot divide or modulo by zero', 'divide-by-zero-float.php'); |
||||
} |
||||
|
||||
public function testLiteralStringDivideByZeroDoesNotCompile(): void |
||||
{ |
||||
$this->exec('Cannot divide or modulo by zero', 'divide-by-zero-string.php'); |
||||
} |
||||
|
||||
public function testLiteralModuloByZeroDoesNotCompile(): void |
||||
{ |
||||
$this->exec('Cannot divide or modulo by zero', 'modulo-by-zero-int.php'); |
||||
} |
||||
|
||||
public function testLiteralDivideAssignByZeroDoesNotCompile(): void |
||||
{ |
||||
$this->exec('Cannot divide or modulo by zero', 'assign-divide-by-zero.php'); |
||||
} |
||||
|
||||
public function testLiteralModuloAssignByZeroDoesNotCompile(): void |
||||
{ |
||||
$this->exec('Cannot divide or modulo by zero', 'assign-modulo-by-zero.php'); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue