Skip to content

Commit ea9deed

Browse files
committed
Factory, Extractor: sets flag readonly for promoted properties [Closes #158]
1 parent b4da526 commit ea9deed

File tree

7 files changed

+30
-3
lines changed

7 files changed

+30
-3
lines changed

src/PhpGenerator/Extractor.php

+3
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,9 @@ private function addMethodToClass(ClassLike $class, Node\Stmt\ClassMethod $node)
343343
$method->setStatic($node->isStatic());
344344
$method->setVisibility($this->toVisibility($node->flags));
345345
$this->setupFunction($method, $node);
346+
if ($method->getName() === Method::Constructor && $class instanceof ClassType && $class->isReadOnly()) {
347+
array_map(fn($param) => $param instanceof PromotedParameter ? $param->setReadOnly() : $param, $method->getParameters());
348+
}
346349
}
347350

348351

src/PhpGenerator/Factory.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ public function fromCallable(callable $from): Method|GlobalFunction|Closure
200200
public function fromParameterReflection(\ReflectionParameter $from): Parameter
201201
{
202202
$param = $from->isPromoted()
203-
? new PromotedParameter($from->name)
203+
? (new PromotedParameter($from->name))->setReadOnly(PHP_VERSION_ID >= 80100 && $from->getDeclaringClass()->getProperty($from->name)->isReadonly())
204204
: new Parameter($from->name);
205205
$param->setReference($from->isPassedByReference());
206206
$param->setType((string) $from->getType());

src/PhpGenerator/Method.php

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ final class Method
2323
use Traits\CommentAware;
2424
use Traits\AttributeAware;
2525

26+
public const Constructor = '__construct';
27+
2628
private bool $static = false;
2729
private bool $final = false;
2830
private bool $abstract = false;

src/PhpGenerator/Printer.php

+4
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,10 @@ public function printClass(
193193
}
194194

195195
foreach ($class->getMethods() as $method) {
196+
if ($readOnlyClass && $method->getName() === Method::Constructor) {
197+
$method = clone $method;
198+
array_map(fn($param) => $param instanceof PromotedParameter ? $param->setReadOnly(false) : null, $method->getParameters());
199+
}
196200
$methods[] = $this->printMethod($method, $namespace, $class->isInterface());
197201
}
198202
}

tests/PhpGenerator/ClassType.from.81.phpt

+2
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,7 @@ require __DIR__ . '/../bootstrap.php';
1212
require __DIR__ . '/fixtures/classes.81.php';
1313

1414
$res[] = ClassType::from(new Abc\Class11);
15+
$res[] = ClassType::from(Abc\Attr::class);
16+
$res[] = ClassType::from(Abc\Class12::class);
1517

1618
sameFile(__DIR__ . '/expected/ClassType.from.81.expect', implode("\n", $res));

tests/PhpGenerator/ClassType.readonly.phpt

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ require __DIR__ . '/fixtures/classes.82.php';
1515

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

2020
$file = (new Extractor(file_get_contents(__DIR__ . '/fixtures/classes.82.php')))->extractAll();
2121
$class = $file->getClasses()[Abc\Class13::class];
2222
Assert::true($class->getProperty('foo')->isReadOnly());
23-
Assert::false($class->getMethod('__construct')->getParameter('bar')->isReadOnly());
23+
Assert::true($class->getMethod('__construct')->getParameter('bar')->isReadOnly());

tests/PhpGenerator/expected/ClassType.from.81.expect

+16
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,19 @@ class Class11
1616
{
1717
}
1818
}
19+
20+
#[\Attribute]
21+
class Attr
22+
{
23+
}
24+
25+
class Class12
26+
{
27+
private readonly string $bar;
28+
29+
30+
public function __construct(
31+
public readonly string $foo,
32+
) {
33+
}
34+
}

0 commit comments

Comments
 (0)