mirror of
https://github.com/danog/psalm.git
synced 2024-11-27 04:45:20 +01:00
Fix #2974 - interpret interfaces a little better
This commit is contained in:
parent
b6380ae595
commit
532ce576cc
@ -462,16 +462,16 @@ class Methods
|
|||||||
|
|
||||||
foreach ($type->getAtomicTypes() as $key => $atomic_type) {
|
foreach ($type->getAtomicTypes() as $key => $atomic_type) {
|
||||||
if ($atomic_type instanceof Type\Atomic\TTemplateParam) {
|
if ($atomic_type instanceof Type\Atomic\TTemplateParam) {
|
||||||
if ($atomic_type->defining_class === $base_fq_class_name) {
|
$types_to_add = self::getExtendedTemplatedTypes(
|
||||||
if (isset($extends[$base_fq_class_name][$atomic_type->param_name])) {
|
$atomic_type,
|
||||||
$extended_param = $extends[$base_fq_class_name][$atomic_type->param_name];
|
$extends
|
||||||
|
|
||||||
$type->removeType($key);
|
|
||||||
$type = Type::combineUnionTypes(
|
|
||||||
$type,
|
|
||||||
$extended_param,
|
|
||||||
$codebase
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ($types_to_add) {
|
||||||
|
$type->removeType($key);
|
||||||
|
|
||||||
|
foreach ($types_to_add as $extra_added_type) {
|
||||||
|
$type->addType($extra_added_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -536,6 +536,37 @@ class Methods
|
|||||||
return $type;
|
return $type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, array<int|string, Type\Union>> $extends
|
||||||
|
* @return list<Type\Atomic>
|
||||||
|
*/
|
||||||
|
private static function getExtendedTemplatedTypes(
|
||||||
|
Type\Atomic\TTemplateParam $atomic_type,
|
||||||
|
array $extends
|
||||||
|
) : array {
|
||||||
|
$extra_added_types = [];
|
||||||
|
|
||||||
|
if (isset($extends[$atomic_type->defining_class][$atomic_type->param_name])) {
|
||||||
|
$extended_param = clone $extends[$atomic_type->defining_class][$atomic_type->param_name];
|
||||||
|
|
||||||
|
foreach ($extended_param->getAtomicTypes() as $extended_atomic_type) {
|
||||||
|
if ($extended_atomic_type instanceof Type\Atomic\TTemplateParam) {
|
||||||
|
$extra_added_types = \array_merge(
|
||||||
|
$extra_added_types,
|
||||||
|
self::getExtendedTemplatedTypes(
|
||||||
|
$extended_atomic_type,
|
||||||
|
$extends
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$extra_added_types[] = $extended_atomic_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $extra_added_types;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
|
@ -3198,6 +3198,39 @@ class ClassTemplateExtendsTest extends TestCase
|
|||||||
}
|
}
|
||||||
}'
|
}'
|
||||||
],
|
],
|
||||||
|
'annotationDefinedInInheritedInterface' => [
|
||||||
|
'<?php
|
||||||
|
/**
|
||||||
|
* @template T1
|
||||||
|
*/
|
||||||
|
interface X {
|
||||||
|
/**
|
||||||
|
* @param T1 $x
|
||||||
|
* @return T1
|
||||||
|
*/
|
||||||
|
public function boo($x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template T2
|
||||||
|
* @extends X<T2>
|
||||||
|
*/
|
||||||
|
interface Y extends X {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template T3
|
||||||
|
* @implements Y<T3>
|
||||||
|
*/
|
||||||
|
class A implements Y {
|
||||||
|
public function boo($x) {
|
||||||
|
return $x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function foo(A $a) : void {
|
||||||
|
$a->boo("boo");
|
||||||
|
}'
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user