fix(cli): support Composer entrypoint and isolate stub symbols

master
韩天峰 24 hours ago
parent 8ddd04e1b1
commit af2b03c111
  1. 4
      .php-cs-fixer.dist.php
  2. 10
      bin/analyze-test-coverage.php
  3. 19
      bin/bootstrap.php
  4. 2
      bin/dump-ast.php
  5. 6
      bin/tpc.php
  6. 6
      composer.json
  7. 5
      composer.lock
  8. 4
      phpunit/BashCompletionTest.php
  9. 188
      phpunit/BinaryEntrypointTest.php
  10. 2
      phpunit/bootstrap.php
  11. 4
      phpunit/src/ArrayDefTest.php
  12. 2
      phpunit/src/Backend/BackendTest.php
  13. 2
      phpunit/src/BigNumericValidationTest.php
  14. 2
      phpunit/src/BranchPredictionTest.php
  15. 4
      phpunit/src/ClassConstantCodegenTest.php
  16. 4
      phpunit/src/ClassMethodOverrideTest.php
  17. 12
      phpunit/src/ClassTest.php
  18. 4
      phpunit/src/CloneWithCodegenTest.php
  19. 4
      phpunit/src/ClosureTest.php
  20. 2
      phpunit/src/CompactTest.php
  21. 2
      phpunit/src/CompileTimeAttributeRegistryTest.php
  22. 41
      phpunit/src/CompilerBaseApiTest.php
  23. 6
      phpunit/src/CompilerPhaseTest.php
  24. 4
      phpunit/src/ConstantArithmeticOverflowTest.php
  25. 2
      phpunit/src/CountGlobalsTest.php
  26. 2
      phpunit/src/DuplicateTest.php
  27. 4
      phpunit/src/ForeachIndentTest.php
  28. 2
      phpunit/src/FunctionTest.php
  29. 6
      phpunit/src/GenStubVersionFlagsTest.php
  30. 8
      phpunit/src/GeneratedCodeCommentTest.php
  31. 4
      phpunit/src/GeneratedCodeIndentationTest.php
  32. 4
      phpunit/src/Generator/FiberGeneratorTest.php
  33. 4
      phpunit/src/HotPathCodegenTest.php
  34. 8
      phpunit/src/InheritanceErrorTest.php
  35. 2
      phpunit/src/InterfacePropertyHookTest.php
  36. 16
      phpunit/src/LocalVariableInitializerTest.php
  37. 4
      phpunit/src/LoopOptimizerTest.php
  38. 2
      phpunit/src/MultiReturnTest.php
  39. 4
      phpunit/src/NativeClass/NativeClassValidationTest.php
  40. 4
      phpunit/src/NativePropertyTest.php
  41. 8
      phpunit/src/NativeScalarBinaryOperandTest.php
  42. 4
      phpunit/src/NewObjectCodegenTest.php
  43. 6
      phpunit/src/OperatorTest.php
  44. 2
      phpunit/src/ParallelCompileTest.php
  45. 70
      phpunit/src/Python/PythonModuleTest.php
  46. 2
      phpunit/src/PythonTools/PythonToolsCommandTest.php
  47. 2
      phpunit/src/ScopedCallContextTest.php
  48. 4
      phpunit/src/ShiftBoundaryTest.php
  49. 4
      phpunit/src/StringConcatAssignTest.php
  50. 2
      phpunit/src/Testing/TestCoverageAnalyzerTest.php
  51. 8
      phpunit/src/TypeCheckGeneratorTest.php
  52. 2
      phpunit/src/WasiUnsupportedSyntaxTest.php
  53. 2
      phpunit/src/WrapperArgumentMoveTest.php
  54. 23
      src/CompilerBase.php
  55. 2
      src/Parser/AssignOpTrait.php
  56. 4
      src/Parser/ConstantExpressionTrait.php
  57. 2
      src/Parser/ForeachTrait.php
  58. 2
      src/Preprocessor.php
  59. 7
      src/Translator.php
  60. 21
      src/compiler.php
  61. 54
      src/functions.php
  62. 42
      src/gen_stub.php

@ -1,9 +1,9 @@
<?php
$header = <<<'EOF'
This file is part of Swoole-Compiler(AOT).
This file is part of TypePHP(AOT).
@link https://www.swoole.com/
@link https://www.swoole.com/aot/
@contact service@swoole.com
EOF;

@ -71,11 +71,11 @@ if ($paths === []) {
}
try {
$analyzer = new TestCoverageAnalyzer(ROOT_PATH, $phpVersions);
$analyzer = new TestCoverageAnalyzer(TYPEPHP_ROOT_PATH, $phpVersions);
$report = $analyzer->analyze(
$paths,
$includePhpUnit ? ROOT_PATH . '/phpunit/src' : null,
$includePhpUnit ? ROOT_PATH . '/phpunit/code' : null,
$includePhpUnit ? TYPEPHP_ROOT_PATH . '/phpunit/src' : null,
$includePhpUnit ? TYPEPHP_ROOT_PATH . '/phpunit/code' : null,
);
} catch (Throwable $error) {
fwrite(STDERR, 'Coverage analysis failed: ' . $error->getMessage() . PHP_EOL);
@ -91,7 +91,7 @@ $rendered = match ($format) {
if ($output === null) {
echo $rendered;
} else {
$outputPath = isAbsolutePath($output) ? $output : ROOT_PATH . DIRECTORY_SEPARATOR . $output;
$outputPath = isAbsolutePath($output) ? $output : TYPEPHP_ROOT_PATH . DIRECTORY_SEPARATOR . $output;
$directory = dirname($outputPath);
if (!is_dir($directory) && !mkdir($directory, 0777, true) && !is_dir($directory)) {
fwrite(STDERR, 'Unable to create output directory: ' . $directory . PHP_EOL);
@ -101,7 +101,7 @@ if ($output === null) {
fwrite(STDERR, 'Unable to write report: ' . $outputPath . PHP_EOL);
exit(1);
}
echo 'Wrote ', $format, ' coverage report: ', relativePath(ROOT_PATH, $outputPath), PHP_EOL;
echo 'Wrote ', $format, ' coverage report: ', relativePath(TYPEPHP_ROOT_PATH, $outputPath), PHP_EOL;
}
if ($strict && ($report['parse_errors'] !== [] || $report['unresolved_phpunit_fixtures'] !== [])) {

@ -1,6 +1,17 @@
<?php
define("ROOT_PATH", dirname(__DIR__));
define('DEBUG', true);
/**
* This file is part of TypePHP(AOT).
*
* @link https://www.swoole.com/aot/
* @contact service@swoole.com
*/
require ROOT_PATH . '/vendor/autoload.php';
require ROOT_PATH . '/src/functions.php';
define('TYPEPHP_ROOT_PATH', dirname(__DIR__));
define('TYPEPHP_DEBUG', true);
// Composer bin proxies provide the consuming project's autoloader. A source
// checkout and a packaged compiler keep their own autoloader below TYPEPHP_ROOT_PATH.
$autoloadPath = $GLOBALS['_composer_autoload_path'] ?? TYPEPHP_ROOT_PATH . '/vendor/autoload.php';
unset($GLOBALS['_composer_autoload_path']);
require $autoloadPath;
unset($autoloadPath);

@ -8,7 +8,7 @@
*
* 示例:
* php bin/dump-ast.php examples/hello.php
* php bin/dump-ast.php src/functions.php
* php bin/dump-ast.php src/compiler.php
*/
require_once __DIR__ . '/../vendor/autoload.php';

@ -1,9 +1,9 @@
#!/usr/bin/env php
<?php
require __DIR__ . '/bootstrap.php';
require __DIR__ . '/../src/polyfills.php';
require __DIR__ . '/../src/gen_stub.php';
require __DIR__ . '/../src/compiler.php';
require TYPEPHP_ROOT_PATH . '/src/polyfills.php';
require TYPEPHP_ROOT_PATH . '/src/gen_stub.php';
require TYPEPHP_ROOT_PATH . '/src/compiler.php';
const TYPEPHP_PHP_SCRIPT_ENTRY = true;
main($argc, $argv);

@ -7,13 +7,15 @@
],
"require": {
"php": ">=8.4 <8.6",
"nikic/php-parser": "5.6.1",
"composer-runtime-api": "^2.2",
"nikic/php-parser": "^5.6",
"league/climate": "^3.10",
"marcj/topsort": "^2.0",
"symfony/var-dumper": "^8.0",
"symfony/yaml": "^8.0",
"swoole/phpx": "~2.6.4",
"ajaxray/ansikit": "^0.3.1"
"ajaxray/ansikit": "^0.3",
"ext-dom": "*"
},
"require-dev": {
"phpunit/phpunit": "^10.4",

5
composer.lock generated

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "3262f7344d1d75ad17fdbf19f9f8896d",
"content-hash": "2d4aeff65ded28c1339be3c4f55f55eb",
"packages": [
{
"name": "ajaxray/ansikit",
@ -4925,7 +4925,8 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=8.4 <8.6"
"php": ">=8.4 <8.6",
"composer-runtime-api": "^2.2"
},
"platform-dev": {},
"plugin-api-version": "2.9.0"

@ -12,7 +12,7 @@ final class BashCompletionTest extends TestCase
{
self::assertSame(
BashCompletion::render(),
file_get_contents(ROOT_PATH . '/completions/tpc.bash'),
file_get_contents(TYPEPHP_ROOT_PATH . '/completions/tpc.bash'),
);
}
@ -46,7 +46,7 @@ final class BashCompletionTest extends TestCase
public function testBashScriptSyntaxAndRepresentativeCompletions(): void
{
$script = ROOT_PATH . '/completions/tpc.bash';
$script = TYPEPHP_ROOT_PATH . '/completions/tpc.bash';
self::assertSame('', $this->runBash("bash -n " . escapeshellarg($script)));
self::assertStringNotContainsString('mapfile', file_get_contents($script));
self::assertSame(

@ -0,0 +1,188 @@
<?php
/**
* This file is part of TypePHP(AOT).
*
* @link https://www.swoole.com/aot/
* @contact service@swoole.com
*/
use PHPUnit\Framework\TestCase;
/**
* @internal
* @coversNothing
*/
final class BinaryEntrypointTest extends TestCase
{
public function testBootstrapConstantsUseTypePhpPrefix(): void
{
self::assertFalse(defined('ROOT_PATH'));
self::assertFalse(defined('DEBUG'));
self::assertSame(realpath(__DIR__ . '/..'), TYPEPHP_ROOT_PATH);
self::assertTrue(TYPEPHP_DEBUG);
}
public function testStubGeneratorDoesNotPolluteTheGlobalSymbolTable(): void
{
self::assertTrue(function_exists('TypePhp\\StubGenerator\\generateStubFile'));
self::assertTrue(class_exists('TypePhp\\StubGenerator\\ClassInfo'));
self::assertFalse(function_exists('generateStubFile'));
self::assertFalse(class_exists('ClassInfo'));
}
public function testSourceCheckoutEntrypointUsesPackageAutoloader(): void
{
$temporaryRoot = sys_get_temp_dir() . '/typephp-source-bin-' . bin2hex(random_bytes(6));
self::assertTrue(mkdir($temporaryRoot, 0777, true));
try {
$result = $this->runCompiler(TYPEPHP_ROOT_PATH . '/bin/tpc.php', $temporaryRoot);
self::assertSame(0, $result['status'], $result['stderr']);
self::assertStringContainsString('TypePHP Compiler (AOT)', $result['stdout']);
} finally {
$this->removeDirectory($temporaryRoot);
}
}
public function testComposerVendorEntrypointUsesProjectAutoloader(): void
{
$temporaryRoot = sys_get_temp_dir() . '/typephp-composer-bin-' . bin2hex(random_bytes(6));
$packageRoot = $temporaryRoot . '/vendor/swoole/typephp';
try {
$proxy = $this->createComposerEntrypoint($temporaryRoot, $packageRoot);
self::assertDirectoryDoesNotExist($packageRoot . '/vendor');
$result = $this->runCompiler($proxy, $temporaryRoot);
self::assertSame(0, $result['status'], $result['stderr']);
self::assertStringContainsString('TypePHP Compiler (AOT)', $result['stdout']);
} finally {
$this->removeDirectory($temporaryRoot);
}
}
public function testComposerVendorEntrypointDryCompilesProject(): void
{
if (!$this->hasPhpxLibrary()) {
self::markTestSkipped('A built PHPX library is required for the Zend PHP compiler integration test');
}
$temporaryRoot = sys_get_temp_dir() . '/typephp-composer-project-' . bin2hex(random_bytes(6));
$packageRoot = $temporaryRoot . '/vendor/swoole/typephp';
try {
$proxy = $this->createComposerEntrypoint($temporaryRoot, $packageRoot);
self::assertNotFalse(file_put_contents(
$temporaryRoot . '/main.php',
"<?php\nfunction main(): void {}\n",
));
self::assertNotFalse(file_put_contents(
$temporaryRoot . '/project.yml',
"name: composer-entrypoint-test\nbuild-dir: build\nsources:\n - main.php\n",
));
$result = $this->runCompiler(
$proxy,
$temporaryRoot,
['project.yml', '--dry', '--no-color'],
);
self::assertSame(0, $result['status'], $result['stderr']);
self::assertStringContainsString('Dry run completed:', $result['stdout']);
} finally {
$this->removeDirectory($temporaryRoot);
}
}
/** @return array{status: int, stdout: string, stderr: string} */
private function runCompiler(
string $entrypoint,
string $workingDirectory,
array $arguments = ['--version', '--no-color'],
): array {
$process = proc_open([PHP_BINARY, $entrypoint, ...$arguments], [
0 => ['pipe', 'r'],
1 => ['pipe', 'w'],
2 => ['pipe', 'w'],
], $pipes, $workingDirectory, null, ['suppress_errors' => true]);
self::assertIsResource($process);
fclose($pipes[0]);
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
return [
'status' => proc_close($process),
'stdout' => (string) $stdout,
'stderr' => (string) $stderr,
];
}
private function createComposerEntrypoint(string $temporaryRoot, string $packageRoot): string
{
$this->copyPackageEntrypoint($packageRoot);
$proxy = $temporaryRoot . '/vendor/bin/tpc.php';
$proxySource = sprintf(
"<?php\n\$GLOBALS['_composer_autoload_path'] = %s;\nrequire %s;\n",
var_export(TYPEPHP_ROOT_PATH . '/vendor/autoload.php', true),
var_export($packageRoot . '/bin/tpc.php', true),
);
self::assertNotFalse(file_put_contents($proxy, $proxySource));
return $proxy;
}
private function hasPhpxLibrary(): bool
{
$phpxHome = getenv('PHPX_HOME');
$roots = [TYPEPHP_ROOT_PATH . '/vendor/swoole/phpx'];
if (is_string($phpxHome) && $phpxHome !== '') {
array_unshift($roots, $phpxHome);
}
foreach ($roots as $root) {
foreach (['lib/libphpx.so', 'lib/libphpx.a', 'lib/phpx.lib', 'bin/phpx.dll'] as $library) {
if (is_file($root . '/' . $library)) {
return true;
}
}
}
return false;
}
private function copyPackageEntrypoint(string $packageRoot): void
{
$files = [
'bin/bootstrap.php',
'bin/tpc.php',
'src/compiler.php',
'src/gen_stub.php',
'src/polyfills.php',
];
foreach ($files as $file) {
$destination = $packageRoot . '/' . $file;
$directory = dirname($destination);
if (!is_dir($directory)) {
self::assertTrue(mkdir($directory, 0777, true));
}
self::assertTrue(copy(TYPEPHP_ROOT_PATH . '/' . $file, $destination));
}
self::assertTrue(mkdir(dirname($packageRoot, 2) . '/bin', 0777, true));
}
private function removeDirectory(string $directory): void
{
if (!is_dir($directory)) {
return;
}
$items = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($directory, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::CHILD_FIRST,
);
foreach ($items as $item) {
$item->isDir() ? rmdir($item->getPathname()) : unlink($item->getPathname());
}
rmdir($directory);
}
}

@ -13,7 +13,7 @@ class BaseTest extends TestCase
protected function compile(string $file): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$testFile = __DIR__ . '/code/' . $file;
$compiler->addFiles([$testFile]);

@ -23,9 +23,9 @@ final class ArrayDefTest extends \BaseTest
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/array-def-inclusive-upper-bound.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/array-def-inclusive-upper-bound.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$generated = $compiler->convertFile($source);

@ -252,7 +252,7 @@ class BackendTest extends TestCase
$dir = $this->createTemporaryDirectory('backend_link_failure');
$target = $dir . '/app';
$backend = new Gcc(new Linux(), 'false');
$compiler = new class(ROOT_PATH, $target, $backend) extends CompilerTest {
$compiler = new class(TYPEPHP_ROOT_PATH, $target, $backend) extends CompilerTest {
public function __construct(
string $rootPath,
private readonly string $testTarget,

@ -5,7 +5,7 @@ class BigNumericValidationTest extends \BaseTest
public function testDecimalIntegerOperandDoesNotConvertThroughString(): void
{
global $translator;
$compiler = \TypePhp\CompilerTest::create(ROOT_PATH);
$compiler = \TypePhp\CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$testFile = __DIR__ . '/../code/big-numeric/decimal-int-operand.php';
$compiler->addFiles([$testFile]);

@ -8,7 +8,7 @@ final class BranchPredictionTest extends TestCase
public function testGeneratesExpectedAndUnexpectedMacros(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$file = __DIR__ . '/../code/branch-prediction.php';
$compiler->addFiles([$file]);

@ -20,9 +20,9 @@ final class ClassConstantCodegenTest extends \BaseTest
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/class-constant-codegen.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/class-constant-codegen.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$generated = $compiler->convertFile($source);

@ -6,7 +6,7 @@ class ClassMethodOverrideTest extends \BaseTest
{
public function testChildBeforeParentOverride(): void
{
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$testFile = __DIR__ . '/../code/class-method-override-order.php';
$compiler->addFiles([$testFile]);
$compiler->prepareFile($testFile);
@ -28,7 +28,7 @@ class ClassMethodOverrideTest extends \BaseTest
public function testNamespacedOverrideKeysUseFullClassName(): void
{
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$testFile = __DIR__ . '/../code/class-method-override-namespace.php';
$compiler->addFiles([$testFile]);
$compiler->prepareFile($testFile);

@ -256,7 +256,7 @@ class ClassTest extends \BaseTest
public function testPrinterConvertsNonStringFieldsAndArrayablePreservesValues(): void
{
global $translator;
$compiler = \TypePhp\CompilerTest::create(ROOT_PATH);
$compiler = \TypePhp\CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$testFile = __DIR__ . '/../code/printer-arrayable-field-types.php';
$compiler->addFiles([$testFile]);
@ -298,7 +298,7 @@ class ClassTest extends \BaseTest
public function testNotNullWarnsForExplicitlyNullableParameters(): void
{
global $translator;
$compiler = \TypePhp\CompilerTest::create(ROOT_PATH);
$compiler = \TypePhp\CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$reporter = new class implements \TypePhp\Diagnostics\DiagnosticReporter {
/** @var list<string> */
@ -433,7 +433,7 @@ class ClassTest extends \BaseTest
public function testMethodsForUsesKeywordClassHierarchyAndObjectFallbackPriority(): void
{
global $translator;
$compiler = \TypePhp\CompilerTest::create(ROOT_PATH);
$compiler = \TypePhp\CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$testFile = __DIR__ . '/../code/methods-for-inheritance.php';
$compiler->addFiles([$testFile]);
@ -656,7 +656,7 @@ class ClassTest extends \BaseTest
public function testConstructorCallsParentConstructorWithoutRequiredArguments(): void
{
global $translator;
$compiler = \TypePhp\CompilerTest::create(ROOT_PATH);
$compiler = \TypePhp\CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$testFile = __DIR__ . '/../code/constructor-parent-optional.php';
$compiler->addFiles([$testFile]);
@ -782,7 +782,7 @@ class ClassTest extends \BaseTest
public function testSelfCanBePartOfUnionType()
{
global $translator;
$compiler = \TypePhp\CompilerTest::create(ROOT_PATH);
$compiler = \TypePhp\CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$testFile = __DIR__ . '/../code/union_type_self_allowed.php';
$compiler->addFiles([$testFile]);
@ -794,7 +794,7 @@ class ClassTest extends \BaseTest
public function testParentCanBePartOfUnionType()
{
global $translator;
$compiler = \TypePhp\CompilerTest::create(ROOT_PATH);
$compiler = \TypePhp\CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$testFile = __DIR__ . '/../code/union_type_parent_allowed.php';
$compiler->addFiles([$testFile]);

@ -38,9 +38,9 @@ final class CloneWithCodegenTest extends BaseTest
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/clone-with-codegen.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/clone-with-codegen.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$generated = $compiler->convertFile($source);

@ -8,8 +8,8 @@ class ClosureTest extends \BaseTest
{
global $translator;
$testFile = ROOT_PATH . '/phpunit/code/closure/use-reference-capture.php';
$compiler = CompilerTest::create(ROOT_PATH);
$testFile = TYPEPHP_ROOT_PATH . '/phpunit/code/closure/use-reference-capture.php';
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$compiler->addFiles([$testFile]);
$compiler->prepareFile($testFile);

@ -16,7 +16,7 @@ class CompactTest extends \BaseTest
public function testCompactThisInsideClass(): void
{
$testFile = __DIR__ . '/../code/compact-this-inside-class.php';
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$compiler->addFiles([$testFile]);
$compiler->prepareFile($testFile);
$compiler->convertFile($testFile);

@ -38,7 +38,7 @@ final class CompileTimeAttributeRegistryTest extends TestCase
public function testRegistryMatchesPublicCompileTimeAttributeDeclarations(): void
{
$source = file_get_contents(ROOT_PATH . '/src/polyfills.php');
$source = file_get_contents(TYPEPHP_ROOT_PATH . '/src/polyfills.php');
$this->assertNotFalse($source);
preg_match_all(
'/#\[Attribute\([^\]]+\)\]\s+final readonly class ([A-Za-z_][A-Za-z0-9_]*)/',

@ -415,14 +415,17 @@ PHP);
$internalConstants = $this->getPropertyValue('internalConstants');
$this->assertArrayHasKey('PHP_VERSION', $internalConstants);
$this->assertArrayNotHasKey('ROOT_PATH', $internalConstants);
$this->assertArrayNotHasKey('TYPEPHP_ROOT_PATH', $internalConstants);
$code = $this->invokeMethod(
'parseConstFetch',
new \PhpParser\Node\Expr\ConstFetch(new \PhpParser\Node\Name('ROOT_PATH'))
);
foreach (['ROOT_PATH', 'TYPEPHP_ROOT_PATH'] as $constantName) {
$code = $this->invokeMethod(
'parseConstFetch',
new \PhpParser\Node\Expr\ConstFetch(new \PhpParser\Node\Name($constantName))
);
$this->assertStringStartsWith('php::constant(', $code);
$this->assertStringNotContainsString(ROOT_PATH, $code);
$this->assertStringStartsWith('php::constant(', $code);
$this->assertStringNotContainsString(TYPEPHP_ROOT_PATH, $code);
}
}
public function testUnqualifiedRuntimeConstantUsesNamespaceFallback(): void
@ -1214,11 +1217,11 @@ YAML);
{
global $translator;
foreach ([CompilerBase::BUILD_MODE_BIN, CompilerBase::BUILD_MODE_LIB, CompilerBase::BUILD_MODE_EXT] as $mode) {
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$compiler->setBuildMode($mode);
$testFile = ROOT_PATH . '/phpunit/code/compiler_api/extension_clean_maps.php';
$testFile = TYPEPHP_ROOT_PATH . '/phpunit/code/compiler_api/extension_clean_maps.php';
$compiler->addFiles([$testFile]);
$compiler->prepareFile($testFile);
$compiler->convertFile($testFile);
@ -1245,14 +1248,14 @@ YAML);
public function testGeneratedRuntimeSymbolsUseProjectNamespace(): void
{
global $translator;
$testFile = ROOT_PATH . '/phpunit/code/compiler_api/extension_clean_maps.php';
$testFile = TYPEPHP_ROOT_PATH . '/phpunit/code/compiler_api/extension_clean_maps.php';
foreach ([
CompilerBase::BUILD_MODE_EXT => 'isolated_ext',
CompilerBase::BUILD_MODE_BIN => 'isolated_bin',
CompilerBase::BUILD_MODE_LIB => 'isolated_lib',
] as $mode => $target) {
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$compiler->setBuildMode($mode);
$compiler->setTargetName($target);
@ -1303,11 +1306,11 @@ YAML);
public function testPersistentSymbolCachesAreLazyAndZtsSafe(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$compiler->setBuildMode(CompilerBase::BUILD_MODE_EXT);
$testFile = ROOT_PATH . '/phpunit/code/compiler_api/persistent_symbol_cache.php';
$testFile = TYPEPHP_ROOT_PATH . '/phpunit/code/compiler_api/persistent_symbol_cache.php';
$compiler->addFiles([$testFile]);
$compiler->prepareFile($testFile);
$compiler->convertFile($testFile);
@ -1354,7 +1357,7 @@ YAML);
global $translator;
$translator = $this->compiler;
$testFile = ROOT_PATH . '/phpunit/code/arrayable.php';
$testFile = TYPEPHP_ROOT_PATH . '/phpunit/code/arrayable.php';
$this->compiler->addFiles([$testFile]);
$this->compiler->prepareFile($testFile);
$cppFile = $this->compiler->convertFile($testFile);
@ -1373,7 +1376,7 @@ YAML);
$this->setPropertyValue('buildMode', CompilerBase::BUILD_MODE_LIB);
$this->compiler->setTargetName('prime2');
$testFile = ROOT_PATH . '/phpunit/code/compiler_api/default_argument_abi.stub.php';
$testFile = TYPEPHP_ROOT_PATH . '/phpunit/code/compiler_api/default_argument_abi.stub.php';
$this->compiler->addFiles([$testFile]);
$this->compiler->prepareFile($testFile);
$this->compiler->convertFile($testFile);
@ -1436,7 +1439,7 @@ YAML);
$this->setPropertyValue('buildMode', CompilerBase::BUILD_MODE_LIB);
$this->compiler->setTargetName('prime2');
$testFile = ROOT_PATH . '/phpunit/code/compiler_api/prime2.stub.php';
$testFile = TYPEPHP_ROOT_PATH . '/phpunit/code/compiler_api/prime2.stub.php';
$this->compiler->addFiles([$testFile]);
$this->compiler->prepareFile($testFile);
$this->compiler->convertFile($testFile);
@ -1467,9 +1470,9 @@ YAML);
$this->compiler->setTargetName('prime2');
$files = [
ROOT_PATH . '/phpunit/code/compiler_api/library_import_php.php',
ROOT_PATH . '/phpunit/code/compiler_api/library_import_native.stub.php',
ROOT_PATH . '/phpunit/code/compiler_api/library_import_global.php',
TYPEPHP_ROOT_PATH . '/phpunit/code/compiler_api/library_import_php.php',
TYPEPHP_ROOT_PATH . '/phpunit/code/compiler_api/library_import_native.stub.php',
TYPEPHP_ROOT_PATH . '/phpunit/code/compiler_api/library_import_global.php',
];
$this->compiler->addFiles($files);
$cppFiles = [];
@ -1728,7 +1731,7 @@ YAML);
$this->compiler->setTargetName('namespace_rules');
$stubFile = $this->compiler->genLibraryImportStub([
ROOT_PATH . '/phpunit/code/compiler_api/library_no_export_namespace.php',
TYPEPHP_ROOT_PATH . '/phpunit/code/compiler_api/library_no_export_namespace.php',
]);
$stub = file_get_contents($stubFile);

@ -34,7 +34,7 @@ class CompilerPhaseTest extends \PHPUnit\Framework\TestCase
{
public function testPropertyAccessResolverCannotBeUsedOutsideConvertPhase(): void
{
$compiler = CompilerPhaseProbe::createProbe(ROOT_PATH);
$compiler = CompilerPhaseProbe::createProbe(TYPEPHP_ROOT_PATH);
$this->expectException(TestError::class);
$this->expectExceptionMessage('PropertyAccessResolver can only be used during convert phase');
@ -44,7 +44,7 @@ class CompilerPhaseTest extends \PHPUnit\Framework\TestCase
public function testPropertyAccessResolverCannotBeUsedDuringPreparePhase(): void
{
$compiler = CompilerPhaseProbe::createProbe(ROOT_PATH);
$compiler = CompilerPhaseProbe::createProbe(TYPEPHP_ROOT_PATH);
$compiler->enterPreparePhase();
$this->expectException(TestError::class);
@ -55,7 +55,7 @@ class CompilerPhaseTest extends \PHPUnit\Framework\TestCase
public function testPropertyAccessResolverCanBeUsedDuringConvertPhase(): void
{
$compiler = CompilerPhaseProbe::createProbe(ROOT_PATH);
$compiler = CompilerPhaseProbe::createProbe(TYPEPHP_ROOT_PATH);
$compiler->enterConvertPhase();
$this->assertTrue($compiler->probePropertyAccessResolver());

@ -72,7 +72,7 @@ class ConstantArithmeticOverflowTest extends TestCase
private function compileWithReporter(): object
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$reporter = new class implements DiagnosticReporter {
/** @var list<string> */
@ -101,7 +101,7 @@ class ConstantArithmeticOverflowTest extends TestCase
private function compileNativeFile(string $file): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$compiler->setDiagnosticReporter(new class implements DiagnosticReporter {
public function fatal(string $message): never

@ -23,7 +23,7 @@ class CountGlobalsTest extends \BaseTest
{
// $GLOBALS['key'] 数组访问形式应正常通过编译
$testFile = __DIR__ . '/../code/globals-array-access.php';
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$compiler->addFiles([$testFile]);
$compiler->prepareFile($testFile);
$compiler->convertFile($testFile);

@ -10,7 +10,7 @@ class DuplicateTest extends TestCase
private function exec(string $expected, string $file): void
{
try {
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$testFile = __DIR__ . '/../code/' . $file;
$compiler->addFiles([$testFile]);
$compiler->prepareFile($testFile);

@ -10,9 +10,9 @@ class ForeachIndentTest extends TestCase
public function testObjectForeachRestoresCompilerIndentation(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$file = ROOT_PATH . '/phpunit/code/object-foreach-indent.php';
$file = TYPEPHP_ROOT_PATH . '/phpunit/code/object-foreach-indent.php';
$compiler->addFiles([$file]);
$compiler->prepareFile($file);
$compiler->convertFile($file);

@ -40,7 +40,7 @@ class FunctionTest extends \BaseTest
): void
{
global $translator;
$compiler = \TypePhp\CompilerTest::create(ROOT_PATH);
$compiler = \TypePhp\CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$testFile = __DIR__ . '/../code/' . $filename;
$compiler->addFiles([$testFile]);

@ -1,11 +1,15 @@
<?php
use TypePhp\StubGenerator\EvaluatedValue;
use TypePhp\StubGenerator\VersionFlags;
use const TypePhp\StubGenerator\PHP_70_VERSION_ID;
final class GenStubVersionFlagsTest extends BaseTest
{
public function testPersistentStringMetadataUsesANonRefcountedInternedZval(): void
{
global $translator;
$translator = \TypePhp\CompilerTest::create(ROOT_PATH);
$translator = \TypePhp\CompilerTest::create(TYPEPHP_ROOT_PATH);
$value = EvaluatedValue::createFromExpression(
new PhpParser\Node\Scalar\String_('PHP'),

@ -8,14 +8,14 @@ final class GeneratedCodeCommentTest extends BaseTest
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
if ($debug) {
$property = new ReflectionProperty($compiler, 'debug');
$property->setValue($compiler, true);
}
$source = ROOT_PATH . '/phpunit/code/generated-code-comments.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/generated-code-comments.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$generated = $compiler->convertFile($source);
@ -28,9 +28,9 @@ final class GeneratedCodeCommentTest extends BaseTest
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/' . $file;
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/' . $file;
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$generated = $compiler->convertFile($source);

@ -7,9 +7,9 @@ class GeneratedCodeIndentationTest extends \PHPUnit\Framework\TestCase
public function testNestedStatementsAndZendWrappersAreConsistentlyIndented(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/generated-code-indentation.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/generated-code-indentation.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$cppFile = $compiler->convertFile($source);

@ -10,7 +10,7 @@ class FiberGeneratorTest extends TestCase
{
public function testWasiTargetRejectsGeneratorDuringPreparation(): void
{
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$reflection = new \ReflectionClass($compiler);
$reflection->getProperty('targetPlatform')->setValue($compiler, 'wasm32-wasip2');
$file = __DIR__ . '/../../code/generator-conversion-error.php';
@ -23,7 +23,7 @@ class FiberGeneratorTest extends TestCase
public function testCompilerStateIsRestoredAfterGeneratorConversionError(): void
{
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$file = __DIR__ . '/../../code/generator-conversion-error.php';
$compiler->addFiles([$file]);
$compiler->prepareFile($file);

@ -61,9 +61,9 @@ final class HotPathCodegenTest extends \BaseTest
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/hot-path-codegen.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/hot-path-codegen.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$generated = $compiler->convertFile($source);

@ -9,7 +9,7 @@ class InheritanceErrorTest extends TestCase
private function exec(string $expected, string $file): void
{
try {
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$testFile = __DIR__ . '/../code/' . $file;
$compiler->addFiles([$testFile]);
$compiler->prepareFile($testFile);
@ -24,7 +24,7 @@ class InheritanceErrorTest extends TestCase
private function assertCompiles(string $file): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$testFile = __DIR__ . '/../code/' . $file;
$compiler->addFiles([$testFile]);
@ -357,7 +357,7 @@ class InheritanceErrorTest extends TestCase
public function testInterfaceArrayConstantInitializesRuntimeValue()
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$testFile = __DIR__ . '/../code/interface_array_constant.php';
$compiler->addFiles([$testFile]);
@ -371,7 +371,7 @@ class InheritanceErrorTest extends TestCase
public function testInterfaceArrayConstantPropagatesToImplementingClass()
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$testFile = __DIR__ . '/../code/interface_array_constant_implements.php';
$compiler->addFiles([$testFile]);

@ -9,7 +9,7 @@ final class InterfacePropertyHookTest extends TestCase
private function compileFixture(string $file): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$path = __DIR__ . '/../code/' . $file;
$compiler->addFiles([$path]);

@ -8,9 +8,9 @@ final class LocalVariableInitializerTest extends \BaseTest
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/local-literal-declaration-initializer.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/local-literal-declaration-initializer.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$generated = $compiler->convertFile($source);
@ -40,9 +40,9 @@ final class LocalVariableInitializerTest extends \BaseTest
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/local-literal-declaration-initializer-native.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/local-literal-declaration-initializer-native.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$generated = $compiler->convertFile($source);
@ -61,9 +61,9 @@ final class LocalVariableInitializerTest extends \BaseTest
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/local-constant-declaration-initializer.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/local-constant-declaration-initializer.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$generated = $compiler->convertFile($source);
@ -94,9 +94,9 @@ final class LocalVariableInitializerTest extends \BaseTest
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/local-class-constant-declaration-initializer.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/local-class-constant-declaration-initializer.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$generated = $compiler->convertFile($source);

@ -9,7 +9,7 @@ class LoopOptimizerTest extends \BaseTest
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$testFile = __DIR__ . '/../code/' . $file;
$compiler->addFiles([$testFile]);
@ -17,7 +17,7 @@ class LoopOptimizerTest extends \BaseTest
$compiler->convertFile($testFile);
$this->addToAssertionCount(1);
return ROOT_PATH . '/build/phpunit/code/' . preg_replace('/\.php$/', '.cc', $file);
return TYPEPHP_ROOT_PATH . '/build/phpunit/code/' . preg_replace('/\.php$/', '.cc', $file);
}
public function testForBoundInternalConstantIsFolded(): void

@ -8,7 +8,7 @@ final class MultiReturnTest extends TestCase
public function testGeneratesTupleFastPathAndArrayCompatibilityAdapter(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$file = __DIR__ . '/../code/multi-return-tuple.php';
$compiler->addFiles([$file]);

@ -10,7 +10,7 @@ final class NativeClassValidationTest extends \BaseTest
{
global $translator;
$compiler = \TypePhp\CompilerTest::create(ROOT_PATH);
$compiler = \TypePhp\CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$directory = dirname(__DIR__, 2) . '/code/native-class-forward';
$files = [$directory . '/a.php', $directory . '/b.php'];
@ -29,7 +29,7 @@ final class NativeClassValidationTest extends \BaseTest
{
global $translator;
$compiler = \TypePhp\CompilerTest::create(ROOT_PATH);
$compiler = \TypePhp\CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$directory = dirname(__DIR__, 2) . '/code/native-class-global-forward';
$files = [$directory . '/a.php', $directory . '/b.php'];

@ -9,7 +9,7 @@ class NativePropertyTest extends \BaseTest
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$testFile = __DIR__ . '/../code/' . $file;
$compiler->addFiles([$testFile]);
@ -17,7 +17,7 @@ class NativePropertyTest extends \BaseTest
$compiler->convertFile($testFile);
$this->addToAssertionCount(1);
return ROOT_PATH . '/build/phpunit/code/' . basename($file, '.php') . '.cc';
return TYPEPHP_ROOT_PATH . '/build/phpunit/code/' . basename($file, '.php') . '.cc';
}
public function testFindNativePropertyUsesFullClassNameAcrossBranches(): void

@ -8,9 +8,9 @@ final class NativeScalarBinaryOperandTest extends \BaseTest
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/native-scalar-binary-operands.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/native-scalar-binary-operands.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$generated = $compiler->convertFile($source);
@ -25,9 +25,9 @@ final class NativeScalarBinaryOperandTest extends \BaseTest
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/dynamic-scalar-binary-operands.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/dynamic-scalar-binary-operands.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$generated = $compiler->convertFile($source);

@ -129,9 +129,9 @@ final class NewObjectCodegenTest extends \BaseTest
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/new-object-codegen.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/new-object-codegen.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$generated = $compiler->convertFile($source);

@ -5,7 +5,7 @@ class OperatorTest extends \BaseTest
public function testBooleanLiteralStrictComparisonUsesNativeBoolOperands(): void
{
global $translator;
$compiler = \TypePhp\CompilerTest::create(ROOT_PATH);
$compiler = \TypePhp\CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$testFile = __DIR__ . '/../code/bool-literal-identical.php';
$compiler->addFiles([$testFile]);
@ -25,7 +25,7 @@ class OperatorTest extends \BaseTest
public function testAssignedValueNotIdenticalToNullIsParenthesized(): void
{
global $translator;
$compiler = \TypePhp\CompilerTest::create(ROOT_PATH);
$compiler = \TypePhp\CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$testFile = __DIR__ . '/../code/assign-not-identical-null.php';
$compiler->addFiles([$testFile]);
@ -42,7 +42,7 @@ class OperatorTest extends \BaseTest
public function testDynamicBoolCallInLogicalExpressionIsConvertedToNativeBool(): void
{
global $translator;
$compiler = \TypePhp\CompilerTest::create(ROOT_PATH);
$compiler = \TypePhp\CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$testFile = __DIR__ . '/../code/bool-dynamic-call-logical.php';
$compiler->addFiles([$testFile]);

@ -98,7 +98,7 @@ class ScriptedWaitCompiler extends CompilerTest
public function __construct(private array $waitResults, private array $forkResults = [])
{
parent::__construct(ROOT_PATH);
parent::__construct(TYPEPHP_ROOT_PATH);
$this->noProgress = true;
}

@ -12,9 +12,9 @@ final class PythonModuleTest extends TestCase
public function testStaticallyResolvedPythonCallsUseNativeBridge(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/python/module-access.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/python/module-access.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$cpp = file_get_contents($compiler->convertFile($source));
@ -30,9 +30,9 @@ final class PythonModuleTest extends TestCase
public function testDynamicPythonMethodNameStillUsesZendDispatch(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/python/dynamic-method.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/python/dynamic-method.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$cpp = file_get_contents($compiler->convertFile($source));
@ -44,9 +44,9 @@ final class PythonModuleTest extends TestCase
public function testUsedModuleGeneratesLazyNativeBindingWithoutPhpyLinkage(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/python/module-access.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/python/module-access.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$cppFile = $compiler->convertFile($source);
@ -69,9 +69,9 @@ final class PythonModuleTest extends TestCase
public function testUnusedPythonUseDoesNotGenerateModuleRuntimeState(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/python/unused-module.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/python/unused-module.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$compiler->convertFile($source);
@ -94,9 +94,9 @@ final class PythonModuleTest extends TestCase
public function testFullyQualifiedModuleAttributeUsesNamespaceConstantSyntax(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/python/fully-qualified-module-constant.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/python/fully-qualified-module-constant.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$cpp = file_get_contents($compiler->convertFile($source));
@ -132,9 +132,9 @@ final class PythonModuleTest extends TestCase
public function testNestedModuleUsesPythonDottedImportName(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/python/nested-module.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/python/nested-module.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$compiler->convertFile($source);
@ -147,9 +147,9 @@ final class PythonModuleTest extends TestCase
public function testPhpFunctionAndConstantImportsResolvePythonSymbols(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/python/imported-symbols.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/python/imported-symbols.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$cpp = file_get_contents($compiler->convertFile($source));
@ -166,9 +166,9 @@ final class PythonModuleTest extends TestCase
public function testFullyQualifiedModuleAccessDoesNotRequireUseDeclaration(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/python/fully-qualified-module.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/python/fully-qualified-module.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$cpp = file_get_contents($compiler->convertFile($source));
@ -187,9 +187,9 @@ final class PythonModuleTest extends TestCase
public function testRelativePythonNameInsideNamespaceRemainsPhpName(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/python/relative-module-name.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/python/relative-module-name.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$cpp = file_get_contents($compiler->convertFile($source));
@ -204,11 +204,11 @@ final class PythonModuleTest extends TestCase
public function testSameModuleAcrossFilesUsesOneRuntimeSlot(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$sources = [
ROOT_PATH . '/phpunit/code/python/module-access.php',
ROOT_PATH . '/phpunit/code/python/duplicate-module.php',
TYPEPHP_ROOT_PATH . '/phpunit/code/python/module-access.php',
TYPEPHP_ROOT_PATH . '/phpunit/code/python/duplicate-module.php',
];
$compiler->addFiles($sources);
foreach ($sources as $source) {
@ -223,9 +223,9 @@ final class PythonModuleTest extends TestCase
public function testPythonBuiltinsUseBuiltinsModuleAndPreserveKnownObjectTypes(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/python/builtins.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/python/builtins.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$cpp = file_get_contents($compiler->convertFile($source));
@ -258,9 +258,9 @@ final class PythonModuleTest extends TestCase
public function testNestedPythonNameUsesModuleCallableSyntax(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/python/invalid-builtin-path.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/python/invalid-builtin-path.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$cpp = file_get_contents($compiler->convertFile($source));
@ -274,9 +274,9 @@ final class PythonModuleTest extends TestCase
public function testConstructorOnlyProgramConfiguresObjectPreservingRuntimeLazily(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/python/constructor-only.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/python/constructor-only.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$cpp = file_get_contents($compiler->convertFile($source));
@ -290,9 +290,9 @@ final class PythonModuleTest extends TestCase
public function testPythonOperatorsLowerToTheOperatorModule(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/python/operators.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/python/operators.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$cpp = file_get_contents($compiler->convertFile($source));
@ -309,9 +309,9 @@ final class PythonModuleTest extends TestCase
public function testPythonObjectProtocolUsesNativeCallsAndZendHandlersWhereAppropriate(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/python/object-protocol.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/python/object-protocol.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$cpp = file_get_contents($compiler->convertFile($source));
@ -331,9 +331,9 @@ final class PythonModuleTest extends TestCase
public function testPyObjectConversionMethodsUseTheNativeBridge(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/python/object-conversion-methods.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/python/object-conversion-methods.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$cpp = file_get_contents($compiler->convertFile($source));
@ -351,9 +351,9 @@ final class PythonModuleTest extends TestCase
private function compileFixture(string $file): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/python/' . $file;
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/python/' . $file;
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$compiler->convertFile($source);

@ -130,7 +130,7 @@ final class PythonToolsCommandTest extends TestCase
*/
private function runTpc(array $arguments): array
{
$command = array_merge([PHP_BINARY, ROOT_PATH . '/bin/tpc.php'], $arguments);
$command = array_merge([PHP_BINARY, TYPEPHP_ROOT_PATH . '/bin/tpc.php'], $arguments);
$process = proc_open($command, [
0 => ['pipe', 'r'],
1 => ['pipe', 'w'],

@ -5,7 +5,7 @@ class ScopedCallContextTest extends \BaseTest
public function testMethodCreatesOneReusableCallableScope(): void
{
global $translator;
$compiler = \TypePhp\CompilerTest::create(ROOT_PATH);
$compiler = \TypePhp\CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$testFile = __DIR__ . '/../code/scoped-call-context-reuse.php';
$compiler->addFiles([$testFile]);

@ -118,7 +118,7 @@ class ShiftBoundaryTest extends TestCase
private function compileWithReporter(): object
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$reporter = new class implements DiagnosticReporter {
/** @var list<string> */
@ -147,7 +147,7 @@ class ShiftBoundaryTest extends TestCase
private function compileNativeWithReporter(string $file): CompilerTest
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$compiler->setDiagnosticReporter(new class implements DiagnosticReporter {
public function fatal(string $message): never

@ -8,9 +8,9 @@ final class StringConcatAssignTest extends \BaseTest
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$source = ROOT_PATH . '/phpunit/code/string-concat-assign.php';
$source = TYPEPHP_ROOT_PATH . '/phpunit/code/string-concat-assign.php';
$compiler->addFiles([$source]);
$compiler->prepareFile($source);
$generated = $compiler->convertFile($source);

@ -92,7 +92,7 @@ final class CoverageFixtureTest extends \PHPUnit\Framework\TestCase
}
PHP);
$analyzer = new TestCoverageAnalyzer(ROOT_PATH, ['8.4', '8.5']);
$analyzer = new TestCoverageAnalyzer(TYPEPHP_ROOT_PATH, ['8.4', '8.5']);
$report = $analyzer->analyze(
[$this->testRoot . '/phpt'],
$this->testRoot . '/phpunit-src',

@ -24,7 +24,7 @@ class TypeCheckGeneratorTest extends \PHPUnit\Framework\TestCase
public function testMethodTypeCheckErrorUsesClassQualifiedCallableName(): void
{
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$classDef = new ClassDef('Demo', 0, 'Foo\\Bar');
$functionDef = new FunctionDef('run', 'php::Var', 'Foo\\Bar');
$argInfo = new ArgInfo();
@ -52,7 +52,7 @@ class TypeCheckGeneratorTest extends \PHPUnit\Framework\TestCase
public function testFunctionTypeCheckErrorUsesFunctionQualifiedCallableName(): void
{
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$functionDef = new FunctionDef('run', 'php::Var', 'Foo\\Bar');
$argInfo = new ArgInfo();
$argInfo->name = 'value';
@ -79,7 +79,7 @@ class TypeCheckGeneratorTest extends \PHPUnit\Framework\TestCase
public function testStrictScalarChecksKeepTheFastCheckAndDelegateColdErrors(): void
{
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$functionDef = new FunctionDef('run', 'php::Int', 'Foo\\Bar');
$argInfo = new ArgInfo();
$argInfo->name = 'value';
@ -106,7 +106,7 @@ class TypeCheckGeneratorTest extends \PHPUnit\Framework\TestCase
public function testDynamicStrictScalarArgumentsUseInlinePhpxConversions(): void
{
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$this->setProtectedProperty($compiler, 'noLiteralStrings', true);
foreach ([

@ -11,7 +11,7 @@ class WasiUnsupportedSyntaxTest extends TestCase
/** @dataProvider unsupportedConversionSyntaxProvider */
public function testUnsupportedSyntaxFailsDuringWasiConversion(string $file, string $message): void
{
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
(new \ReflectionClass($compiler))->getProperty('targetPlatform')->setValue($compiler, 'wasm32-wasip2');
$source = __DIR__ . '/../code/' . $file;
$compiler->addFiles([$source]);

@ -8,7 +8,7 @@ final class WrapperArgumentMoveTest extends TestCase
public function testWrapperConsumesOnlyDeadByValueWrappers(): void
{
global $translator;
$compiler = CompilerTest::create(ROOT_PATH);
$compiler = CompilerTest::create(TYPEPHP_ROOT_PATH);
$translator = $compiler;
$file = __DIR__ . '/../code/wrapper-argument-move.php';
$compiler->addFiles([$file]);

@ -30,6 +30,7 @@ use TypePhp\Entity\MethodDef;
use TypePhp\Entity\PropertyDef;
use TypePhp\Exception\DynamicCall;
use TypePhp\Exception\Redo;
use TypePhp\Exception\Unsupported;
use TypePhp\Generator\AnonClassGenerator;
use TypePhp\Generator\CallArgumentGenerator;
use TypePhp\Generator\ClosureGenerator;
@ -575,6 +576,22 @@ class CompilerBase implements PropertyAccessContext
return $this->lang;
}
protected function unsupportedSyntax(NodeAbstract $node): never
{
$message = 'Error: Unsupported ' . $this->getLang() . ' Syntax,';
$message .= ' Line: ' . $this->getLine($node) . ', Type: ' . $this->getType($node) . PHP_EOL;
if ($this->mode === 'cli') {
if (defined('TYPEPHP_DEBUG') && TYPEPHP_DEBUG) {
var_dump($node);
debug_print_backtrace();
}
} else {
header('Content-Type: application/json');
echo json_encode($node, JSON_PRETTY_PRINT);
}
throw new Unsupported($message);
}
protected function getIndent(): string
{
return str_repeat($this->indentStr, $this->indentLevel);
@ -934,7 +951,7 @@ class CompilerBase implements PropertyAccessContext
case 'Expr_YieldFrom':
return $this->parseYieldFromExpr($expr);
default:
abort($expr);
$this->unsupportedSyntax($expr);
break;
}
return '';
@ -1501,7 +1518,7 @@ class CompilerBase implements PropertyAccessContext
case 'Scalar_String':
return $expr->hasAttribute('noLiteralString') ? $this->getInlineString($expr->value) : $this->getLiteralString($expr->value);
default:
abort($expr);
$this->unsupportedSyntax($expr);
break;
}
return '';
@ -1873,7 +1890,7 @@ class CompilerBase implements PropertyAccessContext
$this->fatalError($v, 'Cannot declare function in function');
break;
default:
abort($v);
$this->unsupportedSyntax($v);
break;
}
$lines = array_merge($lines, $this->context->beforeStmtLines);

@ -289,7 +289,7 @@ trait AssignOpTrait
$code .= $this->getIndent() . "{$var} = {$tmpVar}.item({$key});" . PHP_EOL;
}
} else {
abort($item);
$this->unsupportedSyntax($item);
}
}
$this->indentLevel--;

@ -25,7 +25,7 @@ trait ConstantExpressionTrait
}
if ($expr->name->getType() != 'Name' and !($expr->name instanceof Node\Name\FullyQualified)) {
abort($expr);
$this->unsupportedSyntax($expr);
}
$name = $this->parseIdentifier($expr->name);
$name = ltrim($name, '\\');
@ -175,7 +175,7 @@ trait ConstantExpressionTrait
case 'Scalar_MagicConst_Method':
return '"' . $this->escapeString($class) . '::' . $this->escapeString($this->method) . '"';
default:
abort($expr);
$this->unsupportedSyntax($expr);
break;
}
}

@ -88,7 +88,7 @@ trait ForeachTrait
}
$array = $this->parseIdentifier($node->valueVar->var);
if (!$this->hasVar($array) or $node->valueVar->dim === null) {
abort($node->valueVar);
$this->unsupportedSyntax($node->valueVar);
}
$dim = $this->parseIdentifier($node->valueVar->dim);
return $this->getIndent() . "{$array}.offsetSet({$dim}, {$valueExpr});";

@ -1327,7 +1327,7 @@ class Preprocessor extends CompilerBase
$this->foundStrayCode($v);
break;
default:
abort($v);
$this->unsupportedSyntax($v);
break;
}
}

@ -56,6 +56,7 @@ use PhpParser\NodeAbstract;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor\NameResolver;
use PhpParser\NodeVisitor\CloningVisitor;
use function TypePhp\StubGenerator\generateStubFile;
class Translator extends Preprocessor
{
@ -2825,7 +2826,7 @@ CODE;
case 'Stmt_Nop':
break;
default:
abort($v);
$this->unsupportedSyntax($v);
break;
}
}
@ -3012,7 +3013,7 @@ CODE;
case 'Stmt_Nop':
break;
default:
abort($v2);
$this->unsupportedSyntax($v2);
break;
}
}
@ -3630,7 +3631,7 @@ CODE;
$this->parseTraitUse($v, $methodCodes);
break;
default:
abort($v);
$this->unsupportedSyntax($v);
break;
}
}

@ -12,8 +12,18 @@ function main(int $argc, array $argv): void
// memory. The default CLI limit (commonly 128M) is too small for larger builds.
ini_set('memory_limit', '-1');
if (!defined('ROOT_PATH')) {
define("ROOT_PATH", getcwd());
if (!defined('TYPEPHP_ROOT_PATH')) {
define('TYPEPHP_ROOT_PATH', getcwd());
}
if (!defined('TYPEPHP_DEBUG')) {
define('TYPEPHP_DEBUG', true);
}
// The Zend PHP entrypoint loads the consumer project's Composer autoloader
// in bin/bootstrap.php. The AOT compiler starts here directly and therefore
// must load the dependencies packaged alongside tpc itself.
if (!defined('TYPEPHP_PHP_SCRIPT_ENTRY')) {
require_once TYPEPHP_ROOT_PATH . '/vendor/autoload.php';
}
$completionStatus = CompletionCommand::execute($argv);
@ -43,10 +53,9 @@ function main(int $argc, array $argv): void
return;
}
require_once ROOT_PATH . '/vendor/autoload.php';
global $translator;
$translator = new Translator(ROOT_PATH);
$translator = new Translator(TYPEPHP_ROOT_PATH);
$translator->setIndent(' ');
// 扫描所有 PHP 文件,预处理
$files = $translator->prepare($translator->parseArgv($argv));
@ -173,7 +182,7 @@ function compileWasmProgram(array $argv): void
$input,
$buildDir,
$workingDirectory,
ROOT_PATH . DIRECTORY_SEPARATOR . 'build',
TYPEPHP_ROOT_PATH . DIRECTORY_SEPARATOR . 'build',
$profile,
);
} catch (RuntimeException $exception) {
@ -240,7 +249,7 @@ function compileWasmProgram(array $argv): void
}
try {
$phpxDir = PhpxLocator::resolve(ROOT_PATH);
$phpxDir = PhpxLocator::resolve(TYPEPHP_ROOT_PATH);
} catch (RuntimeException $exception) {
fwrite(STDERR, "Unable to locate PHPX: {$exception->getMessage()}\n");
exit(1);

@ -1,54 +0,0 @@
<?php
/**
* This file is part of TypePHP.
*
* @link https://www.swoole.com/
* @contact service@swoole.com
*/
use TypePhp\CompilerBase;
use TypePhp\Exception\Unsupported;
function abort($v)
{
/*
* @var $translator Translator
*/
global $translator;
$lang = $translator->getLang();
$msg = 'Error: Unsupported ' . $lang . ' Syntax,';
$msg .= ' Line: ' . $translator->getLine($v) . ', Type: ' . $translator->getType($v) . PHP_EOL;
if ($translator->mode == 'cli') {
if (DEBUG) {
var_dump($v);
debug_print_backtrace();
}
} else {
header('Content-Type: application/json');
echo json_encode($v, JSON_PRETTY_PRINT);
}
throw new Unsupported($msg);
}
function if_empty_debug($if_expr, $v)
{
if (empty($if_expr)) {
abort($v);
}
}
function if_not_empty_debug($if_expr, $v)
{
if (!empty($if_expr)) {
abort($v);
}
}
function debug()
{
foreach (func_get_args() as $arg) {
var_dump($arg);
}
debug_print_backtrace();
exit;
}

@ -1,6 +1,33 @@
<?php
declare(strict_types=1);
/*
* This file is derived from build/gen_stub.php in php-src and is not
* original TypePHP source code.
*
* Copyright (c) 1999-2024 The PHP Group. All rights reserved.
* The original code is distributed under the PHP License, version 3.01:
* https://www.php.net/license/3_01.txt
*
* TypePHP maintains local adaptations for its AOT compilation pipeline.
*/
namespace TypePhp\StubGenerator;
use Closure;
use DOMCdataSection;
use DOMComment;
use DOMDocument;
use DOMElement;
use DOMNode;
use DOMText;
use Error;
use Exception;
use PhpParser;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use RuntimeException;
use TypePhp;
use TypePhp\Exception\Skip;
use TypePhp\Translator;
use PhpParser\Comment\Doc as DocComment;
@ -68,7 +95,7 @@ function processDirectory(string $dir, Context $context): array {
);
foreach ($it as $file) {
$pathName = $file->getPathName();
if (substr($pathName, -9) === '.stub.php') {
if (str_ends_with($pathName, '.stub.php')) {
$pathNames[] = $pathName;
}
}
@ -544,7 +571,7 @@ class StubType {
public static function fromNode(Node $node): StubType {
if ($node instanceof Node\UnionType || $node instanceof Node\IntersectionType) {
$nestedTypeObjects = array_map(['StubType', 'fromNode'], $node->types);
$nestedTypeObjects = array_map([self::class, 'fromNode'], $node->types);
$types = [];
foreach ($nestedTypeObjects as $typeObject) {
array_push($types, ...$typeObject->types);
@ -1961,9 +1988,9 @@ class FuncInfo {
/* We create an attribute for xmlns, as libxml otherwise force it to be the first one */
//$refentry->setAttribute("xmlns", "http://docbook.org/ns/docbook");
$namespace = $doc->createAttribute('xmlns');
$namespace->value = "http://docbook.org/ns/docbook";
$namespace->value = "https://docbook.org/ns/docbook";
$refentry->setAttributeNode($namespace);
$refentry->setAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink");
$refentry->setAttribute("xmlns:xlink", "https://www.w3.org/1999/xlink");
$refentry->appendChild(new DOMText("\n "));
/* Creation of <refnamediv> */
@ -2571,7 +2598,12 @@ class EvaluatedValue
}
if ($expr instanceof Expr\ClassConstFetch) {
$className = resolveClassConstFetchClassName($expr, ClassInfo::$currentClass);
// TypePHP registers anonymous classes through eval(). Keep
// file-level function calls independent of the eval scope.
$className = \TypePhp\StubGenerator\resolveClassConstFetchClassName(
$expr,
ClassInfo::$currentClass,
);
$originatingConstName = new ClassConstName(
new Name(ltrim($className, '\\')),
$expr->name->toString()

Loading…
Cancel
Save