mirror of
https://github.com/danog/psalm.git
synced 2025-01-21 21:31:13 +01:00
parent
b313971935
commit
94af3b6c51
@ -982,19 +982,28 @@ class ClassAnalyzer extends ClassLikeAnalyzer
|
||||
|
||||
$codebase = $this->getCodebase();
|
||||
|
||||
$property_id = $fq_class_name . '::$' . $property_name;
|
||||
|
||||
$declaring_property_class = $codebase->properties->getDeclaringClassForProperty(
|
||||
$fq_class_name . '::$' . $property_name
|
||||
$property_id
|
||||
);
|
||||
|
||||
if (!$declaring_property_class) {
|
||||
throw new \UnexpectedValueException(
|
||||
'Cannot get declaring class for ' . $fq_class_name . '::$' . $property_name
|
||||
'Cannot get declaring class for ' . $property_id
|
||||
);
|
||||
}
|
||||
|
||||
$fq_class_name = $declaring_property_class;
|
||||
|
||||
$message = 'Property ' . $fq_class_name . '::$' . $property_name . ' does not have a declared type';
|
||||
// gets inherited property type
|
||||
$class_property_type = $codebase->properties->getPropertyType($property_id);
|
||||
|
||||
if ($class_property_type) {
|
||||
return;
|
||||
}
|
||||
|
||||
$message = 'Property ' . $property_id . ' does not have a declared type';
|
||||
|
||||
$class_storage = $codebase->classlike_storage_provider->get($fq_class_name);
|
||||
|
||||
|
@ -86,9 +86,7 @@ class PropertyAssignmentAnalyzer
|
||||
|
||||
$declaring_property_class = $codebase->properties->getDeclaringClassForProperty($property_id);
|
||||
|
||||
$class_storage = $codebase->classlike_storage_provider->get((string)$declaring_property_class);
|
||||
|
||||
$class_property_type = $class_storage->properties[$prop_name]->type;
|
||||
$class_property_type = $codebase->properties->getPropertyType($property_id);
|
||||
|
||||
$class_property_types[] = $class_property_type ? clone $class_property_type : Type::getMixed();
|
||||
|
||||
@ -450,7 +448,7 @@ class PropertyAssignmentAnalyzer
|
||||
}
|
||||
}
|
||||
|
||||
$class_property_type = $property_storage->type;
|
||||
$class_property_type = $codebase->properties->getPropertyType($property_id);
|
||||
|
||||
if (!$class_property_type) {
|
||||
$class_property_type = Type::getMixed();
|
||||
@ -797,7 +795,7 @@ class PropertyAssignmentAnalyzer
|
||||
$context->vars_in_scope[$var_id] = $assignment_value_type;
|
||||
}
|
||||
|
||||
$class_property_type = $property_storage->type;
|
||||
$class_property_type = $codebase->properties->getPropertyType($property_id);
|
||||
|
||||
if (!$class_property_type) {
|
||||
$class_property_type = Type::getMixed();
|
||||
|
@ -488,7 +488,7 @@ class PropertyFetchAnalyzer
|
||||
}
|
||||
}
|
||||
|
||||
$class_property_type = $property_storage->type;
|
||||
$class_property_type = $codebase->properties->getPropertyType($property_id);
|
||||
|
||||
if (!$class_property_type) {
|
||||
if (IssueBuffer::accepts(
|
||||
|
@ -4,6 +4,7 @@ namespace Psalm\Internal\Codebase;
|
||||
use Psalm\CodeLocation;
|
||||
use Psalm\Internal\Provider\ClassLikeStorageProvider;
|
||||
use Psalm\Internal\Provider\FileReferenceProvider;
|
||||
use Psalm\Type;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -150,4 +151,49 @@ class Properties
|
||||
|
||||
throw new \UnexpectedValueException('Property ' . $property_id . ' should exist');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property_id
|
||||
* @return ?Type\Union
|
||||
*/
|
||||
public function getPropertyType($property_id)
|
||||
{
|
||||
// remove trailing backslash if it exists
|
||||
$property_id = preg_replace('/^\\\\/', '', $property_id);
|
||||
|
||||
list($fq_class_name, $property_name) = explode('::$', $property_id);
|
||||
|
||||
$class_storage = $this->classlike_storage_provider->get($fq_class_name);
|
||||
|
||||
if (isset($class_storage->declaring_property_ids[$property_name])) {
|
||||
$declaring_property_class = $class_storage->declaring_property_ids[$property_name];
|
||||
$declaring_class_storage = $this->classlike_storage_provider->get($declaring_property_class);
|
||||
|
||||
if (isset($declaring_class_storage->properties[$property_name])) {
|
||||
$storage = $declaring_class_storage->properties[$property_name];
|
||||
} else {
|
||||
throw new \UnexpectedValueException('Property ' . $property_id . ' should exist');
|
||||
}
|
||||
} else {
|
||||
throw new \UnexpectedValueException('Property ' . $property_id . ' should exist');
|
||||
}
|
||||
|
||||
if ($storage->type) {
|
||||
return $storage->type;
|
||||
}
|
||||
|
||||
if (!isset($class_storage->overridden_property_ids[$property_name])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ($class_storage->overridden_property_ids[$property_name] as $overridden_property_id) {
|
||||
$overridden_storage = $this->getStorage($overridden_property_id);
|
||||
|
||||
if ($overridden_storage->type) {
|
||||
return $overridden_storage->type;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -1174,6 +1174,30 @@ class PropertyTypeTest extends TestCase
|
||||
[],
|
||||
'error_levels' => []
|
||||
],
|
||||
'inheritDocPropertyTypes' => [
|
||||
'<?php
|
||||
class X {
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
public $a;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
public static $b;
|
||||
}
|
||||
|
||||
class Y extends X {
|
||||
public $a = "foo";
|
||||
public static $b = "foo";
|
||||
}
|
||||
|
||||
(new Y)->a = "hello";
|
||||
echo (new Y)->a;
|
||||
Y::$b = "bar";
|
||||
echo Y::$b;',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@ -1867,6 +1891,41 @@ class PropertyTypeTest extends TestCase
|
||||
}',
|
||||
'error_message' => 'UndefinedThisPropertyFetch',
|
||||
],
|
||||
'inheritDocPropertyTypesIncorrectAssignmentToInstanceProperty' => [
|
||||
'<?php
|
||||
class X {
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
public $a;
|
||||
}
|
||||
|
||||
class Y extends X {
|
||||
public $a = "foo";
|
||||
}
|
||||
|
||||
(new Y)->a = 5;
|
||||
echo (new Y)->a;
|
||||
Y::$b = "bar";
|
||||
echo Y::$b;',
|
||||
'error_message' => 'InvalidPropertyAssignmentValue',
|
||||
],
|
||||
'inheritDocPropertyTypesIncorrectAssignmentToStaticProperty' => [
|
||||
'<?php
|
||||
class X {
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
public static $b;
|
||||
}
|
||||
|
||||
class Y extends X {
|
||||
public static $b = "foo";
|
||||
}
|
||||
|
||||
Y::$b = 5;',
|
||||
'error_message' => 'InvalidPropertyAssignmentValue',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user