Skip to content

Commit

Permalink
Hooked properties cannot be both final and private
Browse files Browse the repository at this point in the history
  • Loading branch information
staabm committed Feb 16, 2025
1 parent f2bf43c commit cf7f25d
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/Node/ClassPropertyNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ public function isPrivate(): bool
return (bool) ($this->flags & Modifiers::PRIVATE);
}

public function isFinal(): bool
{
return (bool) ($this->flags & Modifiers::FINAL);
}

public function isStatic(): bool
{
return (bool) ($this->flags & Modifiers::STATIC);
Expand Down
26 changes: 26 additions & 0 deletions src/Rules/Properties/PropertyInClassRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,32 @@ public function processNode(Node $node, Scope $scope): array
];
}

if ($node->isPrivate()) {
if ($node->hasHooks()) {
if ($node->isFinal()) {
return [
RuleErrorBuilder::message('Hooked properties cannot be both final and private.')
->nonIgnorable()
->identifier('property.abstractPrivate')
->build(),
];
}

foreach ($node->getHooks() as $hook) {
if (!$hook->isFinal()) {
continue;
}

return [
RuleErrorBuilder::message('Hooked properties cannot be both final and private.')
->nonIgnorable()
->identifier('property.abstractPrivate')
->build(),
];
}
}
}

if ($node->isReadOnly()) {
if ($node->hasHooks()) {
return [
Expand Down
18 changes: 18 additions & 0 deletions tests/PHPStan/Rules/Properties/PropertyInClassRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -213,4 +213,22 @@ public function testPhp84AndStaticHookedProperties(): void
]);
}

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

$this->analyse([__DIR__ . '/data/private-final-property-hooks.php'], [
[
'Hooked properties cannot be both final and private.',
7,
],
[
'Hooked properties cannot be both final and private.',
11,
],
]);
}

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

namespace PrivateFinalHook;

final class User
{
final private string $privatePropGet = 'mailto: example.org' {
get => 'private:' . $this->privatePropGet;
}

private string $privateSet = 'mailto: example.org' {
final set => 'private:' . $this->privateSet;
}

protected string $protected = 'mailto: example.org' {
final get => 'protected:' . $this->protected;
}

public string $public = 'mailto: example.org' {
final get => 'public:' . $this->public;
}

private string $email = 'mailto: example.org' {
get => 'mailto:' . $this->email;
}

function doFoo(): void
{
$u = new User;
var_dump($u->private);
var_dump($u->protected);
var_dump($u->public);
var_dump($u->email);
}
}

0 comments on commit cf7f25d

Please sign in to comment.