Skip to content

Commit

Permalink
Merge pull request #811 from kukulich/php81-readonly-properties
Browse files Browse the repository at this point in the history
PHP 8.1: Readonly properties
  • Loading branch information
Ocramius authored Oct 14, 2021
2 parents 7bf7481 + 9741c3b commit ded5e4d
Show file tree
Hide file tree
Showing 12 changed files with 50 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/Reflection/Adapter/ReflectionProperty.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,6 @@ public function getAttributes(?string $name = null, int $flags = 0): array

public function isReadOnly(): bool
{
throw new Exception\NotImplemented('Not implemented');
return $this->betterReflectionProperty->isReadOnly();
}
}
5 changes: 5 additions & 0 deletions src/Reflection/ReflectionProperty.php
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,11 @@ public function isInitialized(?object $object = null): bool
}
}

public function isReadOnly(): bool
{
return $this->node->isReadonly();
}

/**
* Get the DocBlock type hints as an array of strings.
*
Expand Down
3 changes: 2 additions & 1 deletion src/Reflection/StringCast/ReflectionPropertyStringCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ public static function toString(ReflectionProperty $propertyReflection): string
$type = $propertyReflection->getType();

return sprintf(
'Property [%s %s%s%s $%s ]',
'Property [%s %s%s%s%s $%s ]',
$stateModifier,
self::visibilityToString($propertyReflection),
$propertyReflection->isStatic() ? ' static' : '',
$propertyReflection->isReadOnly() ? ' readonly' : '',
$type !== null ? sprintf(' %s', $type->__toString()) : '',
$propertyReflection->getName(),
);
Expand Down
2 changes: 2 additions & 0 deletions test/unit/Fixture/ExampleClass.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class ExampleClass
*/
public $publicProperty = __DIR__;

public readonly int $readOnlyProperty;

public static $publicStaticProperty;

public function __construct(private ?int $promotedProperty = 123, $noPromotedProperty = null)
Expand Down
9 changes: 5 additions & 4 deletions test/unit/Fixture/ExampleClassExport.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Class [ <user> class Roave\BetterReflectionTest\Fixture\ExampleClass ] {
@@ %s/test/unit/Fixture/ExampleClass.php 10-50
@@ %s/test/unit/Fixture/ExampleClass.php 10-52

- Constants [5] {
Constant [ public integer MY_CONST_1 ] { 123 }
Expand All @@ -16,16 +16,17 @@ Class [ <user> class Roave\BetterReflectionTest\Fixture\ExampleClass ] {
- Static methods [0] {
}

- Properties [4] {
- Properties [5] {
Property [ <default> private $privateProperty ]
Property [ <default> protected $protectedProperty ]
Property [ <default> public $publicProperty ]
Property [ <default> public readonly int $readOnlyProperty ]
Property [ <default> private ?int $promotedProperty ]
}

- Methods [2] {
Method [ <user, ctor> public method __construct ] {
@@ %s/test/unit/Fixture/ExampleClass.php 43 - 45
@@ %s/test/unit/Fixture/ExampleClass.php 45 - 47

- Parameters [2] {
Parameter #0 [ <optional> ?int $promotedProperty = 123 ]
Expand All @@ -34,7 +35,7 @@ Class [ <user> class Roave\BetterReflectionTest\Fixture\ExampleClass ] {
}

Method [ <user> public method someMethod ] {
@@ %s/test/unit/Fixture/ExampleClass.php 47 - 49
@@ %s/test/unit/Fixture/ExampleClass.php 49 - 51
}
}
}
2 changes: 2 additions & 0 deletions test/unit/Fixture/StringCastClass.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ abstract class StringCastClass extends StringCastClassParent implements StringCa
public int|bool $unionTypeProperty = false;
public ?int $nullableTypeProperty = null;

public readonly int $readOnlyProperty;

public function __construct()
{
}
Expand Down
29 changes: 15 additions & 14 deletions test/unit/Fixture/StringCastClassExpected.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Class [ <user> abstract class Roave\BetterReflectionTest\Fixture\StringCastClass extends Roave\BetterReflectionTest\Fixture\StringCastClassParent implements Roave\BetterReflectionTest\Fixture\StringCastClassInterface2, Roave\BetterReflectionTest\Fixture\StringCastClassInterface ] {
@@ %s/Fixture/StringCastClass.php 26-87
@@ %s/Fixture/StringCastClass.php 26-89

- Constants [4] {
Constant [ public boolean PUBLIC_CONSTANT ] { 1 }
Expand All @@ -14,62 +14,63 @@ Class [ <user> abstract class Roave\BetterReflectionTest\Fixture\StringCastClass

- Static methods [1] {
Method [ <user> static public method staticPublicMethod ] {
@@ %s/Fixture/StringCastClass.php 68 - 70
@@ %s/Fixture/StringCastClass.php 70 - 72
}
}

- Properties [6] {
- Properties [7] {
Property [ <default> private $privateProperty ]
Property [ <default> protected $protectedProperty ]
Property [ <default> public $publicProperty ]
Property [ <default> public int $namedTypeProperty ]
Property [ <default> public int|bool $unionTypeProperty ]
Property [ <default> public ?int $nullableTypeProperty ]
Property [ <default> public readonly int $readOnlyProperty ]
}

- Methods [12] {
Method [ <user, ctor> public method __construct ] {
@@ %s/Fixture/StringCastClass.php 42 - 44
@@ %s/Fixture/StringCastClass.php 44 - 46
}

Method [ <user, dtor> public method __destruct ] {
@@ %s/Fixture/StringCastClass.php 46 - 48
@@ %s/Fixture/StringCastClass.php 48 - 50
}

Method [ <user> public method publicMethod ] {
@@ %s/Fixture/StringCastClass.php 50 - 52
@@ %s/Fixture/StringCastClass.php 52 - 54
}

Method [ <user> protected method protectedMethod ] {
@@ %s/Fixture/StringCastClass.php 54 - 56
@@ %s/Fixture/StringCastClass.php 56 - 58
}

Method [ <user> private method privateMethod ] {
@@ %s/Fixture/StringCastClass.php 58 - 60
@@ %s/Fixture/StringCastClass.php 60 - 62
}

Method [ <user> final public method finalPublicMethod ] {
@@ %s/Fixture/StringCastClass.php 62 - 64
@@ %s/Fixture/StringCastClass.php 64 - 66
}

Method [ <user> abstract public method abstractPublicMethod ] {
@@ %s/Fixture/StringCastClass.php 66 - 66
@@ %s/Fixture/StringCastClass.php 68 - 68
}

Method [ <user> public method noVisibility ] {
@@ %s/Fixture/StringCastClass.php 72 - 74
@@ %s/Fixture/StringCastClass.php 74 - 76
}

Method [ <user, overwrites Roave\BetterReflectionTest\Fixture\StringCastClassParent, prototype Roave\BetterReflectionTest\Fixture\StringCastClassParent> public method overwrittenMethod ] {
@@ %s/Fixture/StringCastClass.php 76 - 78
@@ %s/Fixture/StringCastClass.php 78 - 80
}

Method [ <user, prototype Roave\BetterReflectionTest\Fixture\StringCastClassInterface> public method prototypeMethod ] {
@@ %s/Fixture/StringCastClass.php 80 - 82
@@ %s/Fixture/StringCastClass.php 82 - 84
}

Method [ <user> public method methodWithParameters ] {
@@ %s/Fixture/StringCastClass.php 84 - 86
@@ %s/Fixture/StringCastClass.php 86 - 88

- Parameters [2] {
Parameter #0 [ <required> $a ]
Expand Down
2 changes: 2 additions & 0 deletions test/unit/Fixture/StringCastProperties.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ class StringCastProperties
public int $namedTypeProperty = 0;
public int|bool $unionTypeProperty = false;
public ?int $nullableTypeProperty = null;

public readonly int $readOnlyProperty;
}
2 changes: 1 addition & 1 deletion test/unit/Reflection/Adapter/ReflectionPropertyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public function methodExpectationProvider(): array
['getDefaultValue', null, null, []],
['isPromoted', null, true, []],
['getAttributes', NotImplemented::class, null, []],
['isReadOnly', NotImplemented::class, null, []],
['isReadOnly', null, true, []],
];
}

Expand Down
6 changes: 3 additions & 3 deletions test/unit/Reflection/ReflectionClassTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ public function testGetProperties(): void
$properties = $classInfo->getProperties();

self::assertContainsOnlyInstancesOf(ReflectionProperty::class, $properties);
self::assertCount(5, $properties);
self::assertCount(6, $properties);
}

public function testGetPropertiesDeclaredWithOneKeyword(): void
Expand Down Expand Up @@ -418,15 +418,15 @@ public function getPropertiesWithFilterDataProvider(): array
{
return [
[CoreReflectionProperty::IS_STATIC, 1],
[CoreReflectionProperty::IS_PUBLIC, 2],
[CoreReflectionProperty::IS_PUBLIC, 3],
[CoreReflectionProperty::IS_PROTECTED, 1],
[CoreReflectionProperty::IS_PRIVATE, 2],
[
CoreReflectionProperty::IS_STATIC |
CoreReflectionProperty::IS_PUBLIC |
CoreReflectionProperty::IS_PROTECTED |
CoreReflectionProperty::IS_PRIVATE,
5,
6,
],
];
}
Expand Down
11 changes: 11 additions & 0 deletions test/unit/Reflection/ReflectionPropertyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,17 @@ public function testIsStatic(): void
self::assertTrue($staticProp->isStatic());
}

public function testIsReadOnly(): void
{
$classInfo = $this->reflector->reflectClass(ExampleClass::class);

$notReadOnlyProperty = $classInfo->getProperty('publicProperty');
self::assertFalse($notReadOnlyProperty->isReadOnly());

$readOnlyProperty = $classInfo->getProperty('readOnlyProperty');
self::assertTrue($readOnlyProperty->isReadOnly());
}

/**
* @return array
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public function toStringProvider(): array
['namedTypeProperty', 'Property [ <default> public int $namedTypeProperty ]'],
['unionTypeProperty', 'Property [ <default> public int|bool $unionTypeProperty ]'],
['nullableTypeProperty', 'Property [ <default> public ?int $nullableTypeProperty ]'],
['readOnlyProperty', 'Property [ <default> public readonly int $readOnlyProperty ]'],
];
}

Expand Down

0 comments on commit ded5e4d

Please sign in to comment.