Skip to content

Commit

Permalink
Add support for readonly classes
Browse files Browse the repository at this point in the history
Signed-off-by: Ion Bazan <[email protected]>
  • Loading branch information
IonBazan committed Nov 2, 2022
1 parent 1bfd72d commit 0f49852
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 2 deletions.
1 change: 1 addition & 0 deletions .github/workflows/phpunit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jobs:
- "7.4"
- "8.0"
- "8.1"
- "8.2"
operating-system:
- "ubuntu-latest"

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"homepage": "https://laminas.dev",
"license": "BSD-3-Clause",
"require": {
"php": ">=7.4, <8.2"
"php": ">=7.4, <8.3"
},
"require-dev": {
"ext-phar": "*",
Expand Down
1 change: 1 addition & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<directory name="test"/>
<ignoreFiles>
<directory name="vendor"/>
<directory name="test/Generator/TestAsset"/>
</ignoreFiles>
</projectFiles>

Expand Down
20 changes: 20 additions & 0 deletions src/Generator/ClassGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class ClassGenerator extends AbstractGenerator implements TraitUsageInterface
public const IMPLEMENTS_KEYWORD = 'implements';
public const FLAG_ABSTRACT = 0x01;
public const FLAG_FINAL = 0x02;
public const FLAG_READONLY = 0x04;
private const CONSTRUCTOR_NAME = '__construct';

protected ?FileGenerator $containingFileGenerator = null;
Expand Down Expand Up @@ -85,6 +86,11 @@ public static function fromReflection(ClassReflection $classReflection)
}

$cg->setAbstract($classReflection->isAbstract());
$cg->setFinal($classReflection->isFinal());

if (method_exists($classReflection, 'isReadonly')) {
$cg->setReadonly((bool) $classReflection->isReadonly());
}

// set the namespace
if ($classReflection->inNamespace()) {
Expand Down Expand Up @@ -417,6 +423,16 @@ public function isFinal()
return (bool) ($this->flags & self::FLAG_FINAL);
}

public function setReadonly(bool $isReadonly): self
{
return $isReadonly ? $this->addFlag(self::FLAG_READONLY) : $this->removeFlag(self::FLAG_READONLY);
}

public function isReadonly(): bool
{
return (bool) ($this->flags & self::FLAG_READONLY);
}

/**
* @param ?string $extendedClass
* @psalm-param ?class-string $extendedClass
Expand Down Expand Up @@ -1069,6 +1085,10 @@ public function generate()
$output .= 'final ';
}

if ($this->isReadonly()) {
$output .= 'readonly ';
}

$output .= static::OBJECT_TYPE . ' ' . $this->getName();

if (! empty($this->extendedClass)) {
Expand Down
43 changes: 42 additions & 1 deletion test/Generator/ClassGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Laminas\Code\Generator\PropertyGenerator;
use Laminas\Code\Reflection\ClassReflection;
use LaminasTest\Code\Generator\TestAsset\ClassWithPromotedParameter;
use LaminasTest\Code\Generator\TestAsset\ReadonlyClassWithPromotedParameter;
use LaminasTest\Code\TestAsset\FooClass;
use PHPUnit\Framework\TestCase;
use ReflectionMethod;
Expand Down Expand Up @@ -1186,6 +1187,24 @@ final class SomeClass
{
}
EOS;

$output = $classGenerator->generate();
self::assertSame($expectedOutput, $output, $output);
}

public function testGenerateWithFinalReadonlyFlag(): void
{
$classGenerator = ClassGenerator::fromArray([
'name' => 'SomeClass',
'flags' => ClassGenerator::FLAG_FINAL | ClassGenerator::FLAG_READONLY,
]);

$expectedOutput = <<<EOS
final readonly class SomeClass
{
}
EOS;

$output = $classGenerator->generate();
Expand Down Expand Up @@ -1395,7 +1414,7 @@ public function testClassWithPromotedParameterFromReflection(): void
$expectedOutput = <<<EOS
namespace LaminasTest\Code\Generator\TestAsset;
class ClassWithPromotedParameter
final class ClassWithPromotedParameter
{
public function __construct(private string \$promotedParameter)
{
Expand All @@ -1421,4 +1440,26 @@ public function testFailToGenerateClassWithPromotedParameterOnNonConstructorMeth
new PromotedParameterGenerator('promotedParameter', 'string'),
]);
}

/** @requires PHP >= 8.2 */
public function testReadonlyClassWithPromotedParameterFromReflection(): void
{
$classGenerator = ClassGenerator::fromReflection(
new ClassReflection(ReadonlyClassWithPromotedParameter::class)
);

$expectedOutput = <<<EOS
namespace LaminasTest\Code\Generator\TestAsset;
final readonly class ReadonlyClassWithPromotedParameter
{
public function __construct(private string \$promotedParameter)
{
}
}
EOS;

self::assertEquals($expectedOutput, $classGenerator->generate());
}
}
11 changes: 11 additions & 0 deletions test/Generator/TestAsset/ReadonlyClassWithPromotedParameter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace LaminasTest\Code\Generator\TestAsset;

final readonly class ReadonlyClassWithPromotedParameter
{
public function __construct(private string $promotedParameter) {
}
}

0 comments on commit 0f49852

Please sign in to comment.