Skip to content

Commit

Permalink
OverridingPropertyRule - check for final
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Dec 29, 2024
1 parent c34432b commit da12dc2
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 1 deletion.
9 changes: 8 additions & 1 deletion src/Reflection/Php/PhpPropertyReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,14 @@ public function isAbstract(): TrinaryLogic

public function isFinal(): TrinaryLogic
{
return TrinaryLogic::createFromBoolean($this->reflection->isFinal());
if ($this->reflection->isFinal()) {
return TrinaryLogic::createYes();
}
if ($this->reflection->isPrivate()) {
return TrinaryLogic::createNo();
}

return TrinaryLogic::createFromBoolean($this->isPrivateSet());
}

public function isVirtual(): TrinaryLogic
Expand Down
12 changes: 12 additions & 0 deletions src/Rules/Properties/OverridingPropertyRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,18 @@ public function processNode(Node $node, Scope $scope): array
))->identifier('property.visibility')->nonIgnorable()->build();
}

if ($prototype->isFinal()->yes()) {
$errors[] = RuleErrorBuilder::message(sprintf(
'Property %s::$%s overrides final property %s::$%s.',
$classReflection->getDisplayName(),
$node->getName(),
$prototype->getDeclaringClass()->getDisplayName(),
$node->getName(),
))->identifier('property.parentPropertyFinal')
->nonIgnorable()
->build();
}

$typeErrors = [];
$nativeType = $node->getNativeType();
if ($prototype->hasNativeType()) {
Expand Down
28 changes: 28 additions & 0 deletions tests/PHPStan/Rules/Properties/OverridingPropertyRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;
use function sprintf;
use const PHP_VERSION_ID;

/**
* @extends RuleTestCase<OverridingPropertyRule>
Expand Down Expand Up @@ -171,4 +172,31 @@ public function testBug7692(): void
$this->analyse([__DIR__ . '/data/bug-7692.php'], []);
}

public function testFinal(): void
{
if (PHP_VERSION_ID < 80400) {
$this->markTestSkipped('Test requires PHP 8.4.');
}

$this->reportMaybes = true;
$this->analyse([__DIR__ . '/data/overriding-final-property.php'], [
[
'Property OverridingFinalProperty\Bar::$a overrides final property OverridingFinalProperty\Foo::$a.',
21,
],
[
'Property OverridingFinalProperty\Bar::$b overrides final property OverridingFinalProperty\Foo::$b.',
23,
],
[
'Property OverridingFinalProperty\Bar::$c overrides final property OverridingFinalProperty\Foo::$c.',
25,
],
[
'Property OverridingFinalProperty\Bar::$d overrides final property OverridingFinalProperty\Foo::$d.',
27,
],
]);
}

}
29 changes: 29 additions & 0 deletions tests/PHPStan/Rules/Properties/data/overriding-final-property.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php // lint >= 8.4

namespace OverridingFinalProperty;

class Foo
{

final public $a;

final protected $b;

public private(set) $c;

protected private(set) $d;

}

class Bar extends Foo
{

public $a;

public $b;

public $c;

public $d;

}

0 comments on commit da12dc2

Please sign in to comment.