mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Improve handling of parent method calls
This commit is contained in:
parent
4baa4d70d8
commit
69b05f5052
@ -707,6 +707,28 @@ class StaticCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
null
|
||||
);
|
||||
|
||||
if ($found_generic_params
|
||||
&& $stmt->class instanceof PhpParser\Node\Name
|
||||
&& $stmt->class->parts === ['parent']
|
||||
&& $context->self
|
||||
) {
|
||||
$self_class_storage = $codebase->classlike_storage_provider->get($context->self);
|
||||
|
||||
$extended_types = $self_class_storage->template_type_extends[strtolower($fq_class_name)] ?? [];
|
||||
|
||||
if ($extended_types) {
|
||||
foreach ($extended_types as $type_key => $extended_type) {
|
||||
if (!is_string($type_key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($found_generic_params[$type_key][$fq_class_name])) {
|
||||
$found_generic_params[$type_key][$fq_class_name][0] = clone $extended_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (self::checkMethodArgs(
|
||||
$method_id,
|
||||
$args,
|
||||
|
@ -570,7 +570,10 @@ class Methods
|
||||
|
||||
$appearing_fq_class_storage = $this->classlike_storage_provider->get($appearing_fq_class_name);
|
||||
|
||||
if (!$appearing_fq_class_storage->user_defined && CallMap::inCallMap($appearing_method_id)) {
|
||||
if (!$appearing_fq_class_storage->user_defined
|
||||
&& !$appearing_fq_class_storage->stubbed
|
||||
&& CallMap::inCallMap($appearing_method_id)
|
||||
) {
|
||||
if ($appearing_method_id === 'Closure::fromcallable'
|
||||
&& isset($args[0]->value->inferredType)
|
||||
&& $args[0]->value->inferredType->isSingle()
|
||||
|
@ -1435,7 +1435,7 @@ class Reconciler
|
||||
$codebase,
|
||||
$new_type_part,
|
||||
$existing_type_part,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
$scalar_type_match_found,
|
||||
$type_coerced,
|
||||
|
@ -1319,8 +1319,6 @@ class Union
|
||||
$atomic_type->replaceTemplateTypesWithArgTypes($template_types, $codebase);
|
||||
|
||||
if ($atomic_type instanceof Type\Atomic\TTemplateParam) {
|
||||
$keys_to_unset[] = $key;
|
||||
|
||||
$template_type = null;
|
||||
|
||||
if (isset($template_types[$atomic_type->param_name][$atomic_type->defining_class ?: ''])) {
|
||||
@ -1385,6 +1383,8 @@ class Union
|
||||
}
|
||||
|
||||
if ($template_type) {
|
||||
$keys_to_unset[] = $key;
|
||||
|
||||
foreach ($template_type->types as $template_type_part) {
|
||||
if ($template_type_part instanceof Type\Atomic\TMixed) {
|
||||
$is_mixed = true;
|
||||
@ -1392,12 +1392,6 @@ class Union
|
||||
|
||||
$new_types[$template_type_part->getKey()] = $template_type_part;
|
||||
}
|
||||
} else {
|
||||
if ($atomic_type->as->isSingle()) {
|
||||
$new_types[$key] = array_values($atomic_type->as->getTypes())[0];
|
||||
} else {
|
||||
$new_types[$key] = new Type\Atomic\TMixed;
|
||||
}
|
||||
}
|
||||
} elseif ($atomic_type instanceof Type\Atomic\TTemplateParamClass) {
|
||||
$template_type = isset($template_types[$atomic_type->param_name][$atomic_type->defining_class ?: ''])
|
||||
|
@ -1646,35 +1646,6 @@ class TemplateExtendsTest extends TestCase
|
||||
|
||||
ord((new Child())->example("str"));'
|
||||
],
|
||||
'allowWiderParentType' => [
|
||||
'<?php
|
||||
/**
|
||||
* @template T
|
||||
*/
|
||||
abstract class Stringer {
|
||||
/**
|
||||
* @param T $t
|
||||
*/
|
||||
public static function getString($t, object $o = null) : string {
|
||||
return "hello";
|
||||
}
|
||||
}
|
||||
|
||||
class A {}
|
||||
|
||||
/**
|
||||
* @template-extends Stringer<A>
|
||||
*/
|
||||
class AStringer extends Stringer {
|
||||
public static function getString($t, object $o = null) : string {
|
||||
if ($o) {
|
||||
return parent::getString($o);
|
||||
}
|
||||
|
||||
return "a";
|
||||
}
|
||||
}'
|
||||
],
|
||||
'allowTraitExtendAndImplementWithExplicitParamType' => [
|
||||
'<?php
|
||||
/**
|
||||
@ -2772,6 +2743,36 @@ class TemplateExtendsTest extends TestCase
|
||||
class CovariantFoo extends InvariantFoo {}',
|
||||
'error_message' => 'InvalidTemplateParam'
|
||||
],
|
||||
'preventWiderParentType' => [
|
||||
'<?php
|
||||
/**
|
||||
* @template T
|
||||
*/
|
||||
abstract class Stringer {
|
||||
/**
|
||||
* @param T $t
|
||||
*/
|
||||
public static function getString($t, object $o = null) : string {
|
||||
return "hello";
|
||||
}
|
||||
}
|
||||
|
||||
class A {}
|
||||
|
||||
/**
|
||||
* @template-extends Stringer<A>
|
||||
*/
|
||||
class AStringer extends Stringer {
|
||||
public static function getString($t, object $o = null) : string {
|
||||
if ($o) {
|
||||
return parent::getString($o);
|
||||
}
|
||||
|
||||
return "a";
|
||||
}
|
||||
}',
|
||||
'error_message' => 'ArgumentTypeCoercion'
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user