Skip to content

Commit

Permalink
Factory, Extractor: sets flag readonly for promoted properties [Closes
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed May 12, 2024
1 parent b4da526 commit ea9deed
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 3 deletions.
3 changes: 3 additions & 0 deletions src/PhpGenerator/Extractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,9 @@ private function addMethodToClass(ClassLike $class, Node\Stmt\ClassMethod $node)
$method->setStatic($node->isStatic());
$method->setVisibility($this->toVisibility($node->flags));
$this->setupFunction($method, $node);
if ($method->getName() === Method::Constructor && $class instanceof ClassType && $class->isReadOnly()) {
array_map(fn($param) => $param instanceof PromotedParameter ? $param->setReadOnly() : $param, $method->getParameters());
}
}


Expand Down
2 changes: 1 addition & 1 deletion src/PhpGenerator/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ public function fromCallable(callable $from): Method|GlobalFunction|Closure
public function fromParameterReflection(\ReflectionParameter $from): Parameter
{
$param = $from->isPromoted()
? new PromotedParameter($from->name)
? (new PromotedParameter($from->name))->setReadOnly(PHP_VERSION_ID >= 80100 && $from->getDeclaringClass()->getProperty($from->name)->isReadonly())
: new Parameter($from->name);
$param->setReference($from->isPassedByReference());
$param->setType((string) $from->getType());
Expand Down
2 changes: 2 additions & 0 deletions src/PhpGenerator/Method.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ final class Method
use Traits\CommentAware;
use Traits\AttributeAware;

public const Constructor = '__construct';

private bool $static = false;
private bool $final = false;
private bool $abstract = false;
Expand Down
4 changes: 4 additions & 0 deletions src/PhpGenerator/Printer.php
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ public function printClass(
}

foreach ($class->getMethods() as $method) {
if ($readOnlyClass && $method->getName() === Method::Constructor) {
$method = clone $method;
array_map(fn($param) => $param instanceof PromotedParameter ? $param->setReadOnly(false) : null, $method->getParameters());
}
$methods[] = $this->printMethod($method, $namespace, $class->isInterface());
}
}
Expand Down
2 changes: 2 additions & 0 deletions tests/PhpGenerator/ClassType.from.81.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,7 @@ require __DIR__ . '/../bootstrap.php';
require __DIR__ . '/fixtures/classes.81.php';

$res[] = ClassType::from(new Abc\Class11);
$res[] = ClassType::from(Abc\Attr::class);
$res[] = ClassType::from(Abc\Class12::class);

sameFile(__DIR__ . '/expected/ClassType.from.81.expect', implode("\n", $res));
4 changes: 2 additions & 2 deletions tests/PhpGenerator/ClassType.readonly.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ require __DIR__ . '/fixtures/classes.82.php';

$class = ClassType::from(new Abc\Class13);
Assert::true($class->getProperty('foo')->isReadOnly());
Assert::false($class->getMethod('__construct')->getParameter('bar')->isReadOnly());
Assert::true($class->getMethod('__construct')->getParameter('bar')->isReadOnly());

$file = (new Extractor(file_get_contents(__DIR__ . '/fixtures/classes.82.php')))->extractAll();
$class = $file->getClasses()[Abc\Class13::class];
Assert::true($class->getProperty('foo')->isReadOnly());
Assert::false($class->getMethod('__construct')->getParameter('bar')->isReadOnly());
Assert::true($class->getMethod('__construct')->getParameter('bar')->isReadOnly());
16 changes: 16 additions & 0 deletions tests/PhpGenerator/expected/ClassType.from.81.expect
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,19 @@ class Class11
{
}
}

#[\Attribute]
class Attr
{
}

class Class12
{
private readonly string $bar;


public function __construct(
public readonly string $foo,
) {
}
}

0 comments on commit ea9deed

Please sign in to comment.