parent
a08f73c995
commit
4b8d0eb685
20 changed files with 398 additions and 73 deletions
@ -0,0 +1,7 @@ |
||||
<?php |
||||
|
||||
function generated_code_comments(?stdClass $object): mixed |
||||
{ |
||||
$object?->dynamicMethod(); |
||||
return $object; |
||||
} |
||||
@ -0,0 +1,14 @@ |
||||
<?php |
||||
|
||||
namespace GeneratedCodeUseSpacing; |
||||
|
||||
use Example\First; |
||||
use Example\Second; |
||||
use Example\Third; |
||||
use Example\Fourth; |
||||
|
||||
function createAnonymousObject(): object |
||||
{ |
||||
return new class { |
||||
}; |
||||
} |
||||
@ -0,0 +1,149 @@ |
||||
<?php |
||||
|
||||
use TypePhp\CompilerTest; |
||||
|
||||
final class EmptyTranslationUnitTest extends \BaseTest |
||||
{ |
||||
private string $projectDir; |
||||
private CompilerTest $compiler; |
||||
|
||||
protected function setUp(): void |
||||
{ |
||||
parent::setUp(); |
||||
$this->projectDir = sys_get_temp_dir() . '/typephp_empty_translation_' . bin2hex(random_bytes(6)); |
||||
mkdir($this->projectDir, 0777, true); |
||||
|
||||
global $translator; |
||||
$this->compiler = CompilerTest::create($this->projectDir); |
||||
$translator = $this->compiler; |
||||
} |
||||
|
||||
protected function tearDown(): void |
||||
{ |
||||
$this->removeDirectory($this->projectDir); |
||||
parent::tearDown(); |
||||
} |
||||
|
||||
public function testTraitOnlySourceIsNotAddedToCompilation(): void |
||||
{ |
||||
$trait = $this->writeSource('CompileTimeOnlyTrait.php', <<<'PHP' |
||||
<?php |
||||
|
||||
trait CompileTimeOnlyTrait |
||||
{ |
||||
public function answer(): int |
||||
{ |
||||
return 42; |
||||
} |
||||
} |
||||
PHP); |
||||
$program = $this->writeSource('program.php', <<<'PHP' |
||||
<?php |
||||
|
||||
function main(): void |
||||
{ |
||||
} |
||||
PHP); |
||||
|
||||
$files = [$trait, $program]; |
||||
$this->compiler->addFiles($files); |
||||
foreach ($files as $file) { |
||||
$this->compiler->prepareFile($file); |
||||
} |
||||
|
||||
$traitCpp = $this->compiler->getCppFile($trait); |
||||
$traitObject = $this->compiler->getObjectFile($traitCpp); |
||||
if (!is_dir(dirname($traitCpp))) { |
||||
mkdir(dirname($traitCpp), 0777, true); |
||||
} |
||||
file_put_contents($traitCpp, 'stale translation unit'); |
||||
file_put_contents($traitObject, 'stale object'); |
||||
file_put_contents($traitObject . '.typephp-cache', 'stale metadata'); |
||||
|
||||
$sources = $this->compiler->convert($files); |
||||
|
||||
self::assertNotContains($traitCpp, $sources); |
||||
self::assertContains($this->compiler->getCppFile($program), $sources); |
||||
self::assertFileDoesNotExist($traitCpp); |
||||
self::assertFileDoesNotExist($traitObject); |
||||
self::assertFileDoesNotExist($traitObject . '.typephp-cache'); |
||||
self::assertFileExists($this->compiler->getArgInfoHeaderFile($trait)); |
||||
} |
||||
|
||||
public function testFileContainingTraitAndFunctionStillEmitsTranslationUnit(): void |
||||
{ |
||||
$source = $this->writeSource('mixed.php', <<<'PHP' |
||||
<?php |
||||
|
||||
trait MixedDeclarationTrait |
||||
{ |
||||
public function value(): int |
||||
{ |
||||
return 1; |
||||
} |
||||
} |
||||
|
||||
function mixedDeclarationFunction(): int |
||||
{ |
||||
return 7; |
||||
} |
||||
PHP); |
||||
|
||||
$this->compiler->addFiles([$source]); |
||||
$this->compiler->prepareFile($source); |
||||
$cppFile = $this->compiler->convertFile($source); |
||||
|
||||
self::assertNotNull($cppFile); |
||||
self::assertFileExists($cppFile); |
||||
self::assertStringContainsString('return php::toInt(7L);', file_get_contents($cppFile)); |
||||
} |
||||
|
||||
public function testCompileTimeOnlyLibraryStillEmitsExtensionSource(): void |
||||
{ |
||||
$source = $this->writeSource('LibraryTrait.php', <<<'PHP' |
||||
<?php |
||||
|
||||
trait LibraryTrait |
||||
{ |
||||
public function value(): int |
||||
{ |
||||
return 1; |
||||
} |
||||
} |
||||
PHP); |
||||
|
||||
$this->compiler->setBuildMode('lib'); |
||||
$this->compiler->setOutputPath($this->projectDir . '/app'); |
||||
$this->compiler->addFiles([$source]); |
||||
$this->compiler->prepareFile($source); |
||||
$sources = $this->compiler->convert([$source]); |
||||
|
||||
self::assertCount(1, $sources); |
||||
self::assertStringContainsString('extension-app.cc', $sources[0]); |
||||
self::assertFileExists($sources[0]); |
||||
self::assertFileDoesNotExist($this->compiler->getCppFile($source)); |
||||
} |
||||
|
||||
private function writeSource(string $name, string $source): string |
||||
{ |
||||
$file = $this->projectDir . '/' . $name; |
||||
file_put_contents($file, $source); |
||||
return $file; |
||||
} |
||||
|
||||
private function removeDirectory(string $directory): void |
||||
{ |
||||
if (!is_dir($directory)) { |
||||
return; |
||||
} |
||||
foreach (array_diff(scandir($directory), ['.', '..']) as $entry) { |
||||
$path = $directory . '/' . $entry; |
||||
if (is_dir($path)) { |
||||
$this->removeDirectory($path); |
||||
} else { |
||||
unlink($path); |
||||
} |
||||
} |
||||
rmdir($directory); |
||||
} |
||||
} |
||||
@ -0,0 +1,66 @@ |
||||
<?php |
||||
|
||||
use TypePhp\CompilerTest; |
||||
|
||||
final class GeneratedCodeCommentTest extends BaseTest |
||||
{ |
||||
private function compileProbe(bool $debug): string |
||||
{ |
||||
global $translator; |
||||
|
||||
$compiler = CompilerTest::create(ROOT_PATH); |
||||
$translator = $compiler; |
||||
if ($debug) { |
||||
$property = new ReflectionProperty($compiler, 'debug'); |
||||
$property->setValue($compiler, true); |
||||
} |
||||
|
||||
$source = ROOT_PATH . '/phpunit/code/generated-code-comments.php'; |
||||
$compiler->addFiles([$source]); |
||||
$compiler->prepareFile($source); |
||||
$generated = $compiler->convertFile($source); |
||||
$code = file_get_contents($generated); |
||||
self::assertIsString($code); |
||||
return $code; |
||||
} |
||||
|
||||
private function compileFile(string $file): string |
||||
{ |
||||
global $translator; |
||||
|
||||
$compiler = CompilerTest::create(ROOT_PATH); |
||||
$translator = $compiler; |
||||
$source = ROOT_PATH . '/phpunit/code/' . $file; |
||||
$compiler->addFiles([$source]); |
||||
$compiler->prepareFile($source); |
||||
$generated = $compiler->convertFile($source); |
||||
self::assertNotNull($generated); |
||||
$code = file_get_contents($generated); |
||||
self::assertIsString($code); |
||||
return $code; |
||||
} |
||||
|
||||
public function testReleaseCodeOmitsCompilerExplanatoryComments(): void |
||||
{ |
||||
$code = $this->compileProbe(false); |
||||
|
||||
self::assertStringNotContainsString('// Stmt_', $code); |
||||
self::assertStringNotContainsString('// Nullsafe Operator:', $code); |
||||
self::assertStringNotContainsString('// Method Call:', $code); |
||||
} |
||||
|
||||
public function testDebugCodeKeepsCompilerExplanatoryComments(): void |
||||
{ |
||||
$code = $this->compileProbe(true); |
||||
|
||||
self::assertStringContainsString('// Stmt_', $code); |
||||
self::assertStringContainsString('// Nullsafe Operator:', $code); |
||||
} |
||||
|
||||
public function testCompileTimeUseDeclarationsDoNotEmitBlankLines(): void |
||||
{ |
||||
$code = $this->compileFile('generated-code-use-spacing.php'); |
||||
|
||||
self::assertDoesNotMatchRegularExpression('/0,};(?:[ \t]*\R){3,}/', $code); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue