Skip to content

Commit

Permalink
Part 6. Fix mixin collisions on object methods
Browse files Browse the repository at this point in the history
  • Loading branch information
issidorov committed Sep 9, 2024
1 parent 0ce8418 commit 635d38e
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
use function array_values;
use function count;
use function get_class;
use function in_array;
use function reset;
use function strtolower;

Expand Down Expand Up @@ -702,6 +703,7 @@ private static function handleInvalidClass(

/**
* @param lowercase-string $method_name_lc
* @param string[] $ignore_mixins
* @return array{TNamedObject, ClassLikeStorage, bool, bool, MethodIdentifier, string}
*/
private static function handleMixins(
Expand All @@ -715,7 +717,8 @@ private static function handleMixins(
PhpParser\Node\Expr\MethodCall $stmt,
StatementsAnalyzer $statements_analyzer,
string $fq_class_name,
?string $lhs_var_id
?string $lhs_var_id,
array $ignore_mixins = []
): array {
$method_exists = false;
$naive_method_exists = false;
Expand All @@ -739,6 +742,7 @@ private static function handleMixins(
$statements_analyzer,
$fq_class_name,
$lhs_var_id,
$ignore_mixins,
);
} elseif ($class_storage->mixin_declaring_fqcln
&& $class_storage->namedMixins
Expand All @@ -756,6 +760,7 @@ private static function handleMixins(
$statements_analyzer,
$fq_class_name,
$lhs_var_id,
$ignore_mixins,
);
}

Expand All @@ -771,6 +776,7 @@ private static function handleMixins(

/**
* @param lowercase-string $method_name_lc
* @param string[] $ignore_mixins
* @return array{TNamedObject, ClassLikeStorage, bool, bool, MethodIdentifier, string}
*/
private static function handleTemplatedMixins(
Expand All @@ -784,11 +790,14 @@ private static function handleTemplatedMixins(
PhpParser\Node\Expr\MethodCall $stmt,
StatementsAnalyzer $statements_analyzer,
string $fq_class_name,
?string $lhs_var_id
?string $lhs_var_id,
array $ignore_mixins
): array {
$method_exists = false;
$naive_method_exists = false;

$ignore_mixins[] = $fq_class_name;

if ($class_storage->templatedMixins
&& $lhs_type_part instanceof TGenericObject
&& $class_storage->template_types
Expand Down Expand Up @@ -845,7 +854,7 @@ private static function handleTemplatedMixins(
$method_exists = isset($mixin_class_storage->pseudo_methods[$method_name_lc]);
}

if (!$method_exists) {
if (!$method_exists && !in_array($mixin_fq_class_name, $ignore_mixins)) {
[
$lhs_type_part_new,
$mixin_class_storage,
Expand All @@ -865,6 +874,7 @@ private static function handleTemplatedMixins(
$statements_analyzer,
$mixin_fq_class_name,
$lhs_var_id,
$ignore_mixins,
);
}

Expand Down Expand Up @@ -893,6 +903,7 @@ private static function handleTemplatedMixins(

/**
* @param lowercase-string $method_name_lc
* @param string[] $ignore_mixins
* @return array{TNamedObject, ClassLikeStorage, bool, bool, MethodIdentifier, string}
*/
private static function handleRegularMixins(
Expand All @@ -906,11 +917,14 @@ private static function handleRegularMixins(
PhpParser\Node\Expr\MethodCall $stmt,
StatementsAnalyzer $statements_analyzer,
string $fq_class_name,
?string $lhs_var_id
?string $lhs_var_id,
array $ignore_mixins
): array {
$method_exists = false;
$naive_method_exists = false;

$ignore_mixins[] = $fq_class_name;

foreach ($class_storage->namedMixins as $mixin) {
if (!$class_storage->mixin_declaring_fqcln) {
continue;
Expand Down Expand Up @@ -980,7 +994,7 @@ private static function handleRegularMixins(
$naive_method_exists = true;
}

if (!$method_exists) {
if (!$method_exists && !in_array($mixin_fq_class_name, $ignore_mixins)) {
[
$mixin_lhs_type_part,
$mixin_class_storage,
Expand All @@ -1000,6 +1014,7 @@ private static function handleRegularMixins(
$statements_analyzer,
$mixin_fq_class_name,
$lhs_var_id,
$ignore_mixins,
);
}

Expand Down
50 changes: 50 additions & 0 deletions tests/MixinsDeepTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,56 @@ public function __call(string $name, array $arguments) {}
'$b' => 'int',
],
],
'LowMixinCollision_WithObjectMethods' => [
'code' => <<<'PHP'
<?php
/**
* @mixin Foo
*/
class Foo {
public function __call(string $name, array $arguments) {}
}
$foo = new Foo();
$a = $foo->notExistsMethod();
PHP,
'assertions' => [
'$a' => 'mixed',
],
'ignored_issues' => ['MixedAssignment'],
],
'DeepMixinCollision_WithObjectMethods' => [
'code' => <<<'PHP'
<?php
/**
* @mixin Baz
*/
abstract class Foo {
public function __call(string $name, array $arguments) {}
}
/**
* @mixin Foo
*/
abstract class Bar {
public function __call(string $name, array $arguments) {}
}
/**
* @mixin Bar
*/
class Baz {
public function __call(string $name, array $arguments) {}
}
$baz = new Baz();
$a = $baz->notExistsMethod();
PHP,
'assertions' => [
'$a' => 'mixed',
],
'ignored_issues' => ['MixedAssignment'],
],
];
}
}

0 comments on commit 635d38e

Please sign in to comment.