Skip to content

Commit

Permalink
InheritorViolation was only being triggered on grand-childen classes
Browse files Browse the repository at this point in the history
Fixes #10167
  • Loading branch information
robchett authored and weirdan committed Aug 31, 2023
1 parent cc7ed95 commit e23971c
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 22 deletions.
17 changes: 17 additions & 0 deletions src/Psalm/Internal/Analyzer/ClassAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
use Psalm\Issue\ExtensionRequirementViolation;
use Psalm\Issue\ImplementationRequirementViolation;
use Psalm\Issue\InaccessibleMethod;
use Psalm\Issue\InheritorViolation;
use Psalm\Issue\InternalClass;
use Psalm\Issue\InvalidEnumCaseValue;
use Psalm\Issue\InvalidExtendClass;
Expand Down Expand Up @@ -271,6 +272,22 @@ public function analyze(
);
}

$class_union = new Union([new TNamedObject($fq_class_name)]);
foreach ($storage->parent_classes + $storage->direct_class_interfaces as $parent_class) {
$parent_storage = $codebase->classlikes->getStorageFor($parent_class);
if ($parent_storage && $parent_storage->inheritors) {
if (!UnionTypeComparator::isContainedBy($codebase, $class_union, $parent_storage->inheritors)) {
IssueBuffer::maybeAdd(
new InheritorViolation(
'Class ' . $fq_class_name . ' is not an allowed inheritor of parent class ' . $parent_class,
new CodeLocation($this, $this->class),
),
$this->getSuppressedIssues(),
);
}
}
}


if ($storage->template_types) {
foreach ($storage->template_types as $param_name => $_) {
Expand Down
19 changes: 0 additions & 19 deletions src/Psalm/Internal/Analyzer/ClassLikeAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
use Psalm\Internal\Type\TemplateResult;
use Psalm\Internal\Type\TemplateStandinTypeReplacer;
use Psalm\Issue\InaccessibleProperty;
use Psalm\Issue\InheritorViolation;
use Psalm\Issue\InvalidClass;
use Psalm\Issue\InvalidTemplateParam;
use Psalm\Issue\MissingDependency;
Expand All @@ -29,7 +28,6 @@
use Psalm\StatementsSource;
use Psalm\Storage\ClassLikeStorage;
use Psalm\Type;
use Psalm\Type\Atomic\TNamedObject;
use Psalm\Type\Atomic\TTemplateParam;
use Psalm\Type\Union;
use UnexpectedValueException;
Expand Down Expand Up @@ -332,23 +330,6 @@ public static function checkFullyQualifiedClassLikeName(
return null;
}


$classUnion = new Union([new TNamedObject($fq_class_name)]);
foreach ($class_storage->parent_classes + $class_storage->direct_class_interfaces as $parent_class) {
$parent_storage = $codebase->classlikes->getStorageFor($parent_class);
if ($parent_storage && $parent_storage->inheritors) {
if (!UnionTypeComparator::isContainedBy($codebase, $classUnion, $parent_storage->inheritors)) {
IssueBuffer::maybeAdd(
new InheritorViolation(
'Class ' . $fq_class_name . ' is not an allowed inheritor of parent class ' . $parent_class,
$code_location,
),
$suppressed_issues,
);
}
}
}

foreach ($class_storage->invalid_dependencies as $dependency_class_name => $_) {
// if the implemented/extended class is stubbed, it may not yet have
// been hydrated
Expand Down
3 changes: 0 additions & 3 deletions tests/ClassTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1393,7 +1393,6 @@ class Bar extends Foo {}
*/
class BaseClass {}
class BazClass extends BaseClass {} // this is an error
$a = new BazClass();
PHP,
'error_message' => 'InheritorViolation',
'ignored_issues' => [],
Expand All @@ -1406,7 +1405,6 @@ class BazClass extends BaseClass {} // this is an error
*/
interface BaseInterface {}
class BazClass implements BaseInterface {}
$a = new BazClass();
PHP,
'error_message' => 'InheritorViolation',
'ignored_issues' => [],
Expand All @@ -1423,7 +1421,6 @@ interface InterfaceA {}
*/
interface InterfaceB {}
class BazClass implements InterFaceA, InterFaceB {}
$a = new BazClass();
PHP,
'error_message' => 'InheritorViolation',
'ignored_issues' => [],
Expand Down

0 comments on commit e23971c

Please sign in to comment.