- 添加对字面量除零、模零、赋值除零和赋值模零操作的编译时检查 - 实现对整数、浮点数和字符串类型的零值检测 - 为 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