Skip to content

Commit 9e0f58a

Browse files
committed
Properties cannot be final
1 parent 845da19 commit 9e0f58a

File tree

4 files changed

+65
-2
lines changed

4 files changed

+65
-2
lines changed

src/Php/PhpVersion.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,11 @@ public function supportsPropertyHooks(): bool
357357
return $this->versionId >= 80400;
358358
}
359359

360+
public function supportsNonPrivateFinalProperties(): bool
361+
{
362+
return $this->versionId >= 80400;
363+
}
364+
360365
public function supportsAsymmetricVisibility(): bool
361366
{
362367
return $this->versionId >= 80400;

src/Rules/Properties/PropertyInClassRule.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,18 @@ public function processNode(Node $node, Scope $scope): array
8181
];
8282
}
8383

84+
$node->isFinal()
85+
&& !$node->hasHooks()
86+
&& (!$this->phpVersion->supportsNonPrivateFinalProperties() || $node->isPrivate())
87+
) {
88+
return [
89+
RuleErrorBuilder::message('Properties cannot be final.')
90+
->nonIgnorable()
91+
->identifier('property.final')
92+
->build(),
93+
];
94+
}
95+
8496
if ($node->isPrivate()) {
8597
if ($node->hasHooks()) {
8698
if ($node->isFinal()) {

tests/PHPStan/Rules/Properties/PropertyInClassRuleTest.php

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,14 +221,49 @@ public function testPhp84AndPrivateFinalHookedProperties(): void
221221

222222
$this->analyse([__DIR__ . '/data/private-final-property-hooks.php'], [
223223
[
224-
'Hooked properties cannot be both final and private.',
224+
'Properties cannot be both final and private.',
225225
7,
226226
],
227227
[
228-
'Hooked properties cannot be both final and private.',
228+
'Properties cannot be both final and private.',
229229
11,
230230
],
231231
]);
232232
}
233233

234+
public function testPhp84FinalProperties(): void
235+
{
236+
if (PHP_VERSION_ID < 80400) {
237+
$this->markTestSkipped('Test requires PHP 8.4 or later.');
238+
}
239+
240+
$this->analyse([__DIR__ . '/data/final-properties.php'], [
241+
[
242+
'Properties cannot be final.',
243+
7,
244+
],
245+
]);
246+
}
247+
public function testBeforePhp84FinalProperties(): void
248+
{
249+
if (PHP_VERSION_ID >= 80400) {
250+
$this->markTestSkipped('Test requires PHP 8.3 or earlier.');
251+
}
252+
253+
$this->analyse([__DIR__ . '/data/final-properties.php'], [
254+
[
255+
'Properties cannot be final.',
256+
7,
257+
],
258+
[
259+
'Properties cannot be final.',
260+
8,
261+
],
262+
[
263+
'Properties cannot be final.',
264+
9,
265+
],
266+
]);
267+
}
268+
234269
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace FinalProperties;
4+
5+
final class User
6+
{
7+
final private string $private = 'mailto: example.org';
8+
final protected string $protected = 'mailto: example.org';
9+
final public string $public = 'mailto: example.org';
10+
11+
}

0 commit comments

Comments
 (0)