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

Prevent crash in constructor checks

This commit is contained in:
Matthew Brown 2019-01-09 08:35:53 -05:00
parent 6e585008f2
commit 11bfaaa5f7
2 changed files with 81 additions and 1 deletions

View File

@ -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;

View File

@ -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' => []
],
];
}