Skip to content

Commit

Permalink
Detect mismatch between readonly/non-readonly class parent
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Mar 26, 2024
1 parent 795a560 commit 986cbdf
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 0 deletions.
18 changes: 18 additions & 0 deletions src/Rules/Classes/ExistingClassInClassExtendsRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,24 @@ public function processNode(Node $node, Scope $scope): array
$reflection->getDisplayName(),
))->build();
}

if ($reflection->isClass()) {
if ($node->isReadonly()) {
if (!$reflection->isReadOnly()) {
$messages[] = RuleErrorBuilder::message(sprintf(
'%s extends non-readonly class %s.',
$currentClassName !== null ? sprintf('Readonly class %s', $currentClassName) : 'Anonymous readonly class',
$reflection->getDisplayName(),
))->nonIgnorable()->build();
}
} elseif ($reflection->isReadOnly()) {
$messages[] = RuleErrorBuilder::message(sprintf(
'%s extends readonly class %s.',
$currentClassName !== null ? sprintf('Non-readonly class %s', $currentClassName) : 'Anonymous non-readonly class',
$reflection->getDisplayName(),
))->nonIgnorable()->build();
}
}
}

return $messages;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,30 @@ public function testPhpstanInternalClass(): void
]);
}

public function testReadonly(): void
{
if (PHP_VERSION_ID < 80200) {
$this->markTestSkipped('This test needs PHP 8.2');
}

$this->analyse([__DIR__ . '/data/extends-readonly-class.php'], [
[
'Readonly class ExtendsReadOnlyClass\Foo extends non-readonly class ExtendsReadOnlyClass\Nonreadonly.',
25,
],
[
'Non-readonly class ExtendsReadOnlyClass\Bar extends readonly class ExtendsReadOnlyClass\ReadonlyClass.',
30,
],
[
'Anonymous non-readonly class extends readonly class ExtendsReadOnlyClass\ReadonlyClass.',
35,
],
[
'Anonymous readonly class extends non-readonly class ExtendsReadOnlyClass\Nonreadonly.',
39,
],
]);
}

}
41 changes: 41 additions & 0 deletions tests/PHPStan/Rules/Classes/data/extends-readonly-class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php // lint >= 8.2

namespace ExtendsReadOnlyClass;

class Nonreadonly
{

}

readonly class ReadonlyClass
{

}

class Lorem extends Nonreadonly // ok
{

}

readonly class Ipsum extends ReadonlyClass // ok
{

}

readonly class Foo extends Nonreadonly // not ok
{

}

class Bar extends ReadonlyClass // not ok
{

}

new class extends ReadonlyClass { // not ok

};

new readonly class extends Nonreadonly { // not ok

};

0 comments on commit 986cbdf

Please sign in to comment.