1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 20:34:47 +01:00

Support better mixin handling

This commit is contained in:
Brown 2020-05-27 11:12:09 -04:00
parent 203ed6d94f
commit 3c60609c21
2 changed files with 69 additions and 1 deletions

View File

@ -344,6 +344,20 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
$codebase
);
$lhs_type_expanded = \Psalm\Internal\Type\TypeExpander::expandUnion(
$codebase,
new Type\Union([$lhs_type_part]),
$mixin_declaring_class_storage->name,
$fq_class_name,
$class_storage->parent_class
);
$new_lhs_type_part = array_values($lhs_type_expanded->getAtomicTypes())[0];
if ($new_lhs_type_part instanceof Type\Atomic\TNamedObject) {
$lhs_type_part = $new_lhs_type_part;
}
$mixin_class_storage = $codebase->classlike_storage_provider->get($class_storage->mixin->value);
$fq_class_name = $mixin_class_storage->name;

View File

@ -224,7 +224,7 @@ class MixinAnnotationTest extends TestCase
return $b->foo;
}'
],
'inheritTemplatedMixin' => [
'inheritTemplatedMixinWithStatic' => [
'<?php
/**
* @template T
@ -316,6 +316,60 @@ class MixinAnnotationTest extends TestCase
(new A)->foo();',
'error_message' => 'UndefinedMethod'
],
'inheritTemplatedMixinWithSelf' => [
'<?php
/**
* @template T
*/
class Mixin {
/**
* @psalm-var T
*/
private $var;
/**
* @psalm-param T $var
*/
public function __construct ($var) {
$this->var = $var;
}
/**
* @psalm-return T
*/
public function type() {
return $this->var;
}
}
/**
* @template T as object
* @mixin Mixin<T>
*/
abstract class Foo {
/** @var Mixin<T> */
public object $obj;
public function __call(string $name, array $args) {
return $this->obj->$name(...$args);
}
}
/**
* @extends Foo<self>
*/
abstract class FooChild extends Foo{}
/**
* @psalm-suppress MissingConstructor
*/
final class FooGrandChild extends FooChild {}
function test() : FooGrandChild {
return (new FooGrandChild)->type();
}',
'error_message' => 'LessSpecificReturnStatement'
],
];
}
}