Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions phpunit/code/direct-get-called-class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

class DirectCalledBase
{
final public function instanceName(): string
{
return get_called_class();
}

public static function staticName(): string
{
return \GET_CALLED_CLASS();
}
}

class DirectCalledChild extends DirectCalledBase
{
}

function directCalledName(DirectCalledBase $object): string
{
return $object->instanceName();
}
26 changes: 26 additions & 0 deletions phpunit/code/get-called-class-namespace-fallback.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace CalledClassKnown;

function get_called_class(): string
{
return 'known';
}

class KnownProbe
{
public function name(): string
{
return get_called_class();
}
}

namespace CalledClassDynamic;

class DynamicProbe
{
public function name(): string
{
return get_called_class();
}
}
20 changes: 20 additions & 0 deletions phpunit/code/get-called-class-shadow-alias.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace ExternalFunctions;

function shadow(): string
{
return 'shadow';
}

namespace CalledAlias;

use function ExternalFunctions\shadow as GET_CALLED_CLASS;

class Probe
{
public function name(): string
{
return gEt_CaLlEd_CLaSs();
}
}
42 changes: 42 additions & 0 deletions phpunit/code/namespaced-builtin-fallback-optimizer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php
/**
* This file is part of TypePHP(AOT).
*
* @link https://www.swoole.com/aot/
* @contact service@swoole.com
*/

namespace NamespacedBuiltinFallback;

class Probe
{
private array $blocks;
private int $size = 0;

public function __construct(array $blocks)
{
$this->blocks = $blocks;
}

public function countBlocks(): int
{
$this->size = count($this->blocks);
return $this->size;
}

public function matches(): bool
{
return in_array('needle', $this->blocks, true)
&& str_contains('needle in haystack', 'needle');
}
}

function strlen(string $value): int
{
return 7;
}

function shadowedLength(): int
{
return strlen('ignored');
}
13 changes: 13 additions & 0 deletions phpunit/code/namespaced-restricted-functions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace NamespacedRestricted;

function nano(): void
{
ShElL_ExEc('true');
}

function wasi(): void
{
StReAm_SoCkEt_ClIeNt('tcp://127.0.0.1:80');
}
8 changes: 8 additions & 0 deletions phpunit/code/namespaced-wasi-restricted-function.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace NamespacedRestricted;

function wasi(): void
{
StReAm_SoCkEt_ClIeNt('tcp://127.0.0.1:80');
}
12 changes: 12 additions & 0 deletions phpunit/code/native-class-get-called-class-namespaced.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace NativeCalledClassShort;

#[\Native]
class NativeGetCalledClassShort
{
public function name(): string
{
return gEt_CaLlEd_CLaSs();
}
}
10 changes: 10 additions & 0 deletions phpunit/code/native-class-get-called-class-qualified.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

#[\Native]
class NativeGetCalledClassQualified
{
public function name(): string
{
return \GET_CALLED_CLASS();
}
}
17 changes: 17 additions & 0 deletions phpunit/code/native-class-get-called-class-shadow.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace NativeCalledClassShadow;

function get_called_class(): string
{
return 'shadow';
}

#[\Native]
class NativeGetCalledClassShadow
{
public function name(): string
{
return get_called_class();
}
}
8 changes: 6 additions & 2 deletions phpunit/code/native-class-get-called-class.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
<?php

#[Native]
namespace NativeCalledClass;

use function \get_called_class as CALLED_CLASS;

#[\Native]
class NativeGetCalledClass
{
public function name(): string
{
return get_called_class();
return cAlLeD_cLaSs();
}
}
12 changes: 12 additions & 0 deletions phpunit/code/native-class-get-class-namespaced.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace NativeClassIntrospection;

#[\Native]
class NativeGetClassNamespaced
{
public function name(): string
{
return gEt_CLaSs();
}
}
22 changes: 22 additions & 0 deletions phpunit/code/native-class-get-class-shadow.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace NativeClassIntrospectionShadow;

function get_class(): string
{
return 'class';
}

function get_parent_class(): string
{
return 'parent';
}

#[\Native]
class NativeGetClassShadow
{
public function names(): array
{
return [get_class(), get_parent_class()];
}
}
15 changes: 15 additions & 0 deletions phpunit/code/native-class-get-parent-class-namespaced.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace NativeClassIntrospection;

#[\Native]
class NativeGetParentClassNamespacedBase {}

#[\Native]
class NativeGetParentClassNamespaced extends NativeGetParentClassNamespacedBase
{
public function parentName(): string|false
{
return gEt_PaReNt_ClAsS($this);
}
}
15 changes: 15 additions & 0 deletions phpunit/code/qualified-runtime-function.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Consumer;

use Vendor\Package as Lib;

function imported(): mixed
{
return Lib\runtime_function();
}

function currentNamespace(): mixed
{
return Sub\runtime_function();
}
2 changes: 2 additions & 0 deletions phpunit/code/random-invalid-random-int-arity.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

namespace RandomArity;

function invalidRandomIntArity(): int
{
return random_int(1);
Expand Down
2 changes: 2 additions & 0 deletions phpunit/code/scoped-call-context-reuse.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

namespace ScopedCallContext;

class ScopedCallContextReuse
{
private function mapValue(int $value): int
Expand Down
94 changes: 94 additions & 0 deletions phpunit/src/DirectGetCalledClassTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

use TypePhp\Build\NanoExtensionSelector;
use TypePhp\Analysis\CompilationStatistics;
use TypePhp\CompilerBase;
use TypePhp\CompilerTest;

final class DirectGetCalledClassTest extends BaseTest
{
public function testBuiltinUsesRuntimeCalledClassInInstanceAndStaticMethods(): void
{
global $translator;
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/direct-get-called-class.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$code = file_get_contents($compiler->convertFile($source));

self::assertSame(2, substr_count($code, 'const php::Str _typephp_called_class ='));
self::assertStringNotContainsString('php::call(', $code);
self::assertStringContainsString('php_directcalledbase__instancename(object)', $code);
}

public function testCaseInsensitiveUserFunctionAliasIsNotReplacedWithClassName(): void
{
global $translator;
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/get-called-class-shadow-alias.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$code = file_get_contents($compiler->convertFile($source));

self::assertStringNotContainsString('_typephp_called_class', $code);
self::assertStringContainsString('php_externalfunctions__shadow(', $code);
}

public function testNamespacedFunctionShadowsAndFallsBackAtRuntime(): void
{
global $translator;
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$compiler->setBuildMode(CompilerBase::BUILD_MODE_EXT);
$compiler->setTargetName('get_called_class_fallback');
(new \ReflectionProperty($compiler, 'noLiteralStrings'))->setValue($compiler, true);
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/get-called-class-namespace-fallback.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$code = file_get_contents($compiler->convertFile($source));

self::assertStringContainsString('php_calledclassknown__get_called_class(', $code);
self::assertStringContainsString('php::fn::function_exists(', $code);
self::assertStringContainsString('typephp_call_cached(', $code);
self::assertStringContainsString('_typephp_called_class', $code);
self::assertStringContainsString('CalledClassDynamic\\\\get_called_class', $code);
self::assertStringNotContainsString('ZEND_STRL("get_called_class")', $code);
self::assertSame(1, substr_count($code, 'typephp_get_function_resolution_cache('));
self::assertSame(1, substr_count($code, 'typephp_get_function_call_cache('));
self::assertStringContainsString('resolution == 0', $code);
self::assertStringContainsString('resolution = php::fn::function_exists(', $code);
self::assertStringContainsString(') ? 1 : 2;', $code);
self::assertStringContainsString('resolution == 1', $code);

$extension = file_get_contents($compiler->genExtension());
self::assertIsString($extension);
self::assertStringContainsString('uint8_t function_resolution_cache_map[1]', $extension);
self::assertStringContainsString(
'uint8_t &typephp_get_function_resolution_cache(FunctionResolutionCacheId cache_id)',
$extension,
);

$statistics = $compiler->getCompilationStatistics();
self::assertTrue($statistics->has(CompilationStatistics::DIRECT_FUNCTIONS, 'function_exists'));
$selection = (new NanoExtensionSelector())->select($statistics, ['standard']);
self::assertSame(['standard.core'], $selection->features);
}

public function testQualifiedRuntimeFunctionUsesResolvedTarget(): void
{
global $translator;
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
(new \ReflectionProperty($compiler, 'noLiteralStrings'))->setValue($compiler, true);
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/qualified-runtime-function.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$code = file_get_contents($compiler->convertFile($source));

self::assertStringContainsString('Vendor\\\\Package\\\\runtime_function', $code);
self::assertStringContainsString('Consumer\\\\Sub\\\\runtime_function', $code);
self::assertStringNotContainsString('Lib\\\\runtime_function', $code);
}
}
Loading
Loading