TypePHP 编译器
https://swoole.com/aot/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
6.3 KiB
158 lines
6.3 KiB
<?php
|
|
|
|
use TypePhp\CompilerTest;
|
|
use TypePhp\Exception\TestError;
|
|
|
|
class NativePropertyTest extends \BaseTest
|
|
{
|
|
private function compileNativeProperty(string $file): string
|
|
{
|
|
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);
|
|
return ROOT_PATH . '/build/phpunit/code/' . basename($file, '.php') . '.cc';
|
|
}
|
|
|
|
public function testFindNativePropertyUsesFullClassNameAcrossBranches(): void
|
|
{
|
|
try {
|
|
$this->compileNativeProperty('native-property-full-name.php');
|
|
} catch (TestError $e) {
|
|
$this->fail($e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function testStaticStaticPropertyUsesDynamicCalledClassPath(): void
|
|
{
|
|
try {
|
|
$outputFile = $this->compileNativeProperty('native-property-full-name.php');
|
|
} catch (TestError $e) {
|
|
$this->fail($e->getMessage());
|
|
}
|
|
|
|
$code = file_get_contents($outputFile);
|
|
$this->assertStringContainsString('php::getStaticProperty(php_get_called_class(this_), "count")', $code);
|
|
$this->assertStringContainsString('php::getStaticProperty(php_get_called_class(this_), "count") = php::toInt(value)', $code);
|
|
}
|
|
|
|
public function testNativeIntPropertyAssignOpUsesNativeReference(): void
|
|
{
|
|
try {
|
|
$outputFile = $this->compileNativeProperty('native-property-assign-op-int.php');
|
|
} catch (TestError $e) {
|
|
$this->fail($e->getMessage());
|
|
}
|
|
|
|
$code = file_get_contents($outputFile);
|
|
$this->assertStringContainsString('typephp_static_int_ref(this_.attr(', $code);
|
|
$this->assertStringContainsString('typephp_static_int_ref(box.attr(', $code);
|
|
$this->assertSame(2, substr_count($code, 'typephp_static_int_ref('));
|
|
$this->assertStringNotContainsString('this_.attr(php_get_prop(0, _literal_strings[0], 0, _literal_strings[1]), true) +=', $code);
|
|
$this->assertStringNotContainsString('box.attr(php_get_prop(0, _literal_strings[0], 0, _literal_strings[1]), true) +=', $code);
|
|
}
|
|
|
|
public function testNativeIntPropertyAssignOpConvertsBitwiseNotClassConst(): void
|
|
{
|
|
try {
|
|
$outputFile = $this->compileNativeProperty('native-property-assign-op-class-const.php');
|
|
} catch (TestError $e) {
|
|
$this->fail($e->getMessage());
|
|
}
|
|
|
|
$code = file_get_contents($outputFile);
|
|
$this->assertStringContainsString('typephp_static_int_ref(this_.attr(', $code);
|
|
$this->assertStringContainsString('&= (~php::toInt(php::constant(', $code);
|
|
}
|
|
|
|
public function testNativePropertyWriteConvertsOnlyWhenTypesDiffer(): void
|
|
{
|
|
try {
|
|
$outputFile = $this->compileNativeProperty('native-property-write-conversion.php');
|
|
} catch (TestError $e) {
|
|
$this->fail($e->getMessage());
|
|
}
|
|
|
|
$code = file_get_contents($outputFile);
|
|
$this->assertStringContainsString(' = nativeValue;', $code);
|
|
$this->assertStringContainsString(' = php::toIntExact(dynamicValue, "NativePropertyWriteConversionBox::$value");', $code);
|
|
$this->assertStringNotContainsString(' = php::toInt(nativeValue);', $code);
|
|
}
|
|
|
|
public function testNativeThisPropertyWriteUsesExactHelperOnNativeReference(): void
|
|
{
|
|
try {
|
|
$outputFile = $this->compileNativeProperty('native-property-this-write-conversion.php');
|
|
} catch (TestError $e) {
|
|
$this->fail($e->getMessage());
|
|
}
|
|
|
|
$code = file_get_contents($outputFile);
|
|
$this->assertStringContainsString('php::Int &_object_prop_this___value = Z_LVAL_P(this_.attr(', $code);
|
|
$this->assertStringContainsString('_object_prop_this___value = php::toIntExact(dynamicValue, "NativePropertyThisWriteConversionBox::$value");', $code);
|
|
}
|
|
|
|
public function testNativePropertyStaticScalarTypeMismatchFailsAtCompileTime(): void
|
|
{
|
|
$this->exec(
|
|
'Cannot assign string to property NativePropertyStaticTypeMismatchBox::$value of type int',
|
|
'native-property-static-type-mismatch.php'
|
|
);
|
|
}
|
|
|
|
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');
|
|
}
|
|
|
|
public function testCannotAccessPrivateNativePropertyThroughNullsafe(): void
|
|
{
|
|
$this->exec('Cannot access private property `value` of class `NullsafePrivateOwner`', 'nullsafe-private-property.php');
|
|
}
|
|
|
|
public function testCannotAccessNestedPrivateNativePropertyThroughNullsafe(): void
|
|
{
|
|
$this->exec('Cannot access private property `value` of class `NullsafeNestedChild`', 'nullsafe-nested-private-property.php');
|
|
}
|
|
|
|
public function testCannotAssignThroughNullsafeProperty(): void
|
|
{
|
|
$this->exec("Can't use nullsafe operator in write context", 'nullsafe-write-assign.php');
|
|
}
|
|
|
|
public function testCannotUseCompoundAssignThroughNullsafeProperty(): void
|
|
{
|
|
$this->exec("Can't use nullsafe operator in write context", 'nullsafe-write-assign-op.php');
|
|
}
|
|
|
|
public function testCannotIncrementThroughNullsafeProperty(): void
|
|
{
|
|
$this->exec("Can't use nullsafe operator in write context", 'nullsafe-write-inc.php');
|
|
}
|
|
|
|
public function testCannotUnsetThroughNullsafeProperty(): void
|
|
{
|
|
$this->exec("Can't use nullsafe operator in write context", 'nullsafe-write-unset.php');
|
|
}
|
|
|
|
public function testCannotAssignReferenceToNullsafeProperty(): void
|
|
{
|
|
$this->exec("Can't use nullsafe operator in write context", 'nullsafe-write-assign-ref-left.php');
|
|
}
|
|
|
|
public function testCannotTakeReferenceOfNullsafeProperty(): void
|
|
{
|
|
$this->exec('Cannot take reference of a nullsafe chain', 'nullsafe-write-assign-ref-right.php');
|
|
}
|
|
}
|
|
|