mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Prevent crash in constructor checks
This commit is contained in:
parent
6e585008f2
commit
11bfaaa5f7
@ -102,7 +102,45 @@ class CallAnalyzer
|
||||
) {
|
||||
$method_id = $fq_class_name . '::' . strtolower($method_name);
|
||||
|
||||
$declaring_method_id = (string) $codebase->methods->getDeclaringMethodId($method_id);
|
||||
$declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id);
|
||||
|
||||
if (!$declaring_method_id) {
|
||||
if (isset($context->vars_in_scope['$this'])) {
|
||||
foreach ($context->vars_in_scope['$this']->getTypes() as $atomic_type) {
|
||||
if ($atomic_type instanceof TNamedObject) {
|
||||
$fq_class_name = $atomic_type->value;
|
||||
$method_id = $fq_class_name . '::' . strtolower($method_name);
|
||||
|
||||
$declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id);
|
||||
|
||||
if ($declaring_method_id) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!$atomic_type->extra_types) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($atomic_type->extra_types as $intersection_type) {
|
||||
if ($intersection_type instanceof TNamedObject) {
|
||||
$fq_class_name = $intersection_type->value;
|
||||
$method_id = $fq_class_name . '::' . strtolower($method_name);
|
||||
|
||||
$declaring_method_id = $codebase->methods->getDeclaringMethodId($method_id);
|
||||
|
||||
if ($declaring_method_id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$declaring_method_id) {
|
||||
throw new \UnexpectedValueException('Could not find declaring method for ' . $method_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($context->initialized_methods[$declaring_method_id])) {
|
||||
return;
|
||||
|
@ -1132,6 +1132,48 @@ class PropertyTypeTest extends TestCase
|
||||
|
||||
class B extends A {}',
|
||||
],
|
||||
'noCrashForAbstractConstructorWithInstanceofInterface' => [
|
||||
'<?php
|
||||
abstract class A {
|
||||
/** @var int */
|
||||
public $a;
|
||||
|
||||
public function __construct() {
|
||||
if ($this instanceof I) {
|
||||
$this->a = $this->bar();
|
||||
} else {
|
||||
$this->a = 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface I {
|
||||
public function bar() : int;
|
||||
}',
|
||||
],
|
||||
'SKIPPED-abstractConstructorWithInstanceofClass' => [
|
||||
'<?php
|
||||
abstract class A {
|
||||
/** @var int */
|
||||
public $a;
|
||||
|
||||
public function __construct() {
|
||||
if ($this instanceof B) {
|
||||
$this->a = $this->bar();
|
||||
} else {
|
||||
$this->a = 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
public function bar() : int {
|
||||
return 3;
|
||||
}
|
||||
}',
|
||||
[],
|
||||
'error_levels' => []
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user