diff --git a/composer.json b/composer.json index 431cbc9b..9f79b3be 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "nette/php-generator", - "description": "🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 8.1 features.", + "description": "🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 8.2 features.", "keywords": ["nette", "php", "code", "scaffolding"], "homepage": "https://nette.org", "license": ["BSD-3-Clause", "GPL-2.0-only", "GPL-3.0-only"], @@ -20,7 +20,7 @@ }, "require-dev": { "nette/tester": "^2.4", - "nikic/php-parser": "^4.13", + "nikic/php-parser": "^4.14", "tracy/tracy": "^2.8", "phpstan/phpstan": "^1.0" }, diff --git a/readme.md b/readme.md index d8909baa..01f74159 100644 --- a/readme.md +++ b/readme.md @@ -141,7 +141,7 @@ public function __construct( } ``` -Readonly properties introduced by PHP 8.1 can be marked via `setReadOnly()`. +Readonly properties and classes can be marked via `setReadOnly()`. ------ diff --git a/src/PhpGenerator/ClassType.php b/src/PhpGenerator/ClassType.php index a78a1d8b..1877d163 100644 --- a/src/PhpGenerator/ClassType.php +++ b/src/PhpGenerator/ClassType.php @@ -36,6 +36,7 @@ final class ClassType extends ClassLike private bool $final = false; private bool $abstract = false; private ?string $extends = null; + private bool $readOnly = false; /** @var string[] */ private array $implements = []; @@ -172,6 +173,19 @@ public function isAbstract(): bool } + public function setReadOnly(bool $state = true): static + { + $this->readOnly = $state; + return $this; + } + + + public function isReadOnly(): bool + { + return $this->readOnly; + } + + public function setExtends(?string $name): static { if ($name) { diff --git a/src/PhpGenerator/Extractor.php b/src/PhpGenerator/Extractor.php index 11980a5b..0be2d2d8 100644 --- a/src/PhpGenerator/Extractor.php +++ b/src/PhpGenerator/Extractor.php @@ -246,6 +246,7 @@ private function addClassToFile(PhpFile $phpFile, Node\Stmt\Class_ $node): Class $class->setFinal($node->isFinal()); $class->setAbstract($node->isAbstract()); + $class->setReadOnly(method_exists($node, 'isReadonly') && $node->isReadonly()); $this->addCommentAndAttributes($class, $node); return $class; } diff --git a/src/PhpGenerator/Factory.php b/src/PhpGenerator/Factory.php index 58cc4f32..33c6f115 100644 --- a/src/PhpGenerator/Factory.php +++ b/src/PhpGenerator/Factory.php @@ -56,6 +56,7 @@ public function fromClassReflection( $class = new ClassType($from->getShortName(), new PhpNamespace($from->getNamespaceName())); $class->setFinal($from->isFinal() && $class->isClass()); $class->setAbstract($from->isAbstract() && $class->isClass()); + $class->setReadOnly(PHP_VERSION_ID >= 80200 && $from->isReadOnly()); } $ifaces = $from->getInterfaceNames(); diff --git a/src/PhpGenerator/Printer.php b/src/PhpGenerator/Printer.php index bcc9c75a..c224ad61 100644 --- a/src/PhpGenerator/Printer.php +++ b/src/PhpGenerator/Printer.php @@ -227,6 +227,7 @@ public function printClass( if ($class instanceof ClassType) { $line[] = $class->isAbstract() ? 'abstract' : null; $line[] = $class->isFinal() ? 'final' : null; + $line[] = $class->isReadOnly() ? 'readonly' : null; } $line[] = match (true) { diff --git a/tests/PhpGenerator/ClassType.from.82.phpt b/tests/PhpGenerator/ClassType.from.82.phpt new file mode 100644 index 00000000..5acddad0 --- /dev/null +++ b/tests/PhpGenerator/ClassType.from.82.phpt @@ -0,0 +1,17 @@ +extractAll(); sameFile(__DIR__ . '/expected/Extractor.classes.81.expect', (string) $file); +$file = (new Extractor(file_get_contents(__DIR__ . '/fixtures/classes.82.php')))->extractAll(); +sameFile(__DIR__ . '/expected/Extractor.classes.82.expect', (string) $file); + $file = (new Extractor(file_get_contents(__DIR__ . '/fixtures/enum.php')))->extractAll(); sameFile(__DIR__ . '/expected/Extractor.enum.expect', (string) $file); diff --git a/tests/PhpGenerator/expected/ClassType.from.82.expect b/tests/PhpGenerator/expected/ClassType.from.82.expect new file mode 100644 index 00000000..39bb4484 --- /dev/null +++ b/tests/PhpGenerator/expected/ClassType.from.82.expect @@ -0,0 +1,3 @@ +readonly class Class13 +{ +} diff --git a/tests/PhpGenerator/expected/Extractor.classes.82.expect b/tests/PhpGenerator/expected/Extractor.classes.82.expect new file mode 100644 index 00000000..ea812871 --- /dev/null +++ b/tests/PhpGenerator/expected/Extractor.classes.82.expect @@ -0,0 +1,9 @@ +