Skip to content

Commit

Permalink
ReadOnlyPropertyRule - support for readonly classes
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Sep 29, 2022
1 parent 3e383fc commit c52eb57
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 1 deletion.
8 changes: 8 additions & 0 deletions src/Analyser/NodeScopeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,9 @@ private function processStmtNode(
if ($param->getDocComment() !== null) {
$phpDoc = $param->getDocComment()->getText();
}
if (!$scope->isInClass()) {
throw new ShouldNotHappenException();
}
$nodeCallback(new ClassPropertyNode(
$param->var->name,
$param->flags,
Expand All @@ -513,6 +516,7 @@ private function processStmtNode(
$param,
false,
$scope->isInTrait(),
$scope->getClassReflection()->isReadOnly(),
), $methodScope);
}
}
Expand Down Expand Up @@ -657,6 +661,9 @@ private function processStmtNode(
foreach ($stmt->props as $prop) {
$this->processStmtNode($prop, $scope, $nodeCallback);
[,,,,,,,,,,$isReadOnly, $docComment] = $this->getPhpDocs($scope, $stmt);
if (!$scope->isInClass()) {
throw new ShouldNotHappenException();
}
$nodeCallback(
new ClassPropertyNode(
$prop->name->toString(),
Expand All @@ -668,6 +675,7 @@ private function processStmtNode(
$prop,
$isReadOnly,
$scope->isInTrait(),
$scope->getClassReflection()->isReadOnly(),
),
$scope,
);
Expand Down
3 changes: 2 additions & 1 deletion src/Node/ClassPropertyNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public function __construct(
Node $originalNode,
private bool $isReadonlyByPhpDoc,
private bool $isDeclaredInTrait,
private bool $isReadonlyClass,
)
{
parent::__construct($originalNode->getAttributes());
Expand Down Expand Up @@ -76,7 +77,7 @@ public function isStatic(): bool

public function isReadOnly(): bool
{
return (bool) ($this->flags & Class_::MODIFIER_READONLY);
return (bool) ($this->flags & Class_::MODIFIER_READONLY) || $this->isReadonlyClass;
}

public function isReadOnlyByPhpDoc(): bool
Expand Down
5 changes: 5 additions & 0 deletions src/Reflection/ClassReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,11 @@ public function isEnum(): bool
return $this->reflection->isEnum();
}

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

public function isBackedEnum(): bool
{
if (!$this->reflection instanceof ReflectionEnum) {
Expand Down
10 changes: 10 additions & 0 deletions tests/PHPStan/Rules/Properties/ReadOnlyPropertyRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,14 @@ public function testRule(int $phpVersionId, array $errors): void
$this->analyse([__DIR__ . '/data/read-only-property.php'], $errors);
}

/**
* @dataProvider dataRule
* @param mixed[] $errors
*/
public function testRuleReadonlyClass(int $phpVersionId, array $errors): void
{
$this->phpVersionId = $phpVersionId;
$this->analyse([__DIR__ . '/data/read-only-property-readonly-class.php'], $errors);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php // lint >= 8.2

namespace ReadOnlyPropertyReadonlyClass;

readonly class Foo
{

private int $foo;
private $bar;
private int $baz = 0;

}

readonly final class ErrorResponse
{
public function __construct(public string $message = '')
{
}
}

readonly class StaticReadonlyProperty
{
private static int $foo;
}

0 comments on commit c52eb57

Please sign in to comment.