mirror of
https://github.com/danog/psalm.git
synced 2025-01-22 05:41:20 +01:00
Don’t manipulate property storage during analysis
This commit is contained in:
parent
ee8619f7bb
commit
0034f2e4bd
@ -55,6 +55,11 @@ use function array_keys;
|
||||
*/
|
||||
class ClassAnalyzer extends ClassLikeAnalyzer
|
||||
{
|
||||
/**
|
||||
* @var array<string, Type\Union>
|
||||
*/
|
||||
public $inferred_property_types = [];
|
||||
|
||||
/**
|
||||
* @param PhpParser\Node\Stmt\Class_ $class
|
||||
* @param SourceAnalyzer $source
|
||||
@ -1630,11 +1635,23 @@ class ClassAnalyzer extends ClassLikeAnalyzer
|
||||
|
||||
$property_storage = $class_storage->properties[$property_name];
|
||||
|
||||
if ($property_storage->suggested_type && !$property_storage->suggested_type->isNull()) {
|
||||
$suggested_type = $property_storage->suggested_type;
|
||||
|
||||
if (isset($this->inferred_property_types[$property_name])) {
|
||||
$suggested_type = $suggested_type
|
||||
? Type::combineUnionTypes(
|
||||
$suggested_type,
|
||||
$this->inferred_property_types[$property_name],
|
||||
$codebase
|
||||
)
|
||||
: $this->inferred_property_types[$property_name];
|
||||
}
|
||||
|
||||
if ($suggested_type && !$suggested_type->isNull()) {
|
||||
$message .= ' - consider ' . str_replace(
|
||||
['<mixed, mixed>', '<empty, empty>'],
|
||||
['<array-key, mixed>', '<empty, empty>'],
|
||||
'',
|
||||
(string)$property_storage->suggested_type
|
||||
(string)$suggested_type
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ namespace Psalm\Internal\Analyzer\Statements\Expression\Assignment;
|
||||
use PhpParser;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Stmt\PropertyProperty;
|
||||
use Psalm\Internal\Analyzer\ClassAnalyzer;
|
||||
use Psalm\Internal\Analyzer\ClassLikeAnalyzer;
|
||||
use Psalm\Internal\Analyzer\NamespaceAnalyzer;
|
||||
use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer;
|
||||
@ -660,8 +661,6 @@ class InstancePropertyAssignmentAnalyzer
|
||||
|
||||
$declaring_class_storage = $codebase->classlike_storage_provider->get($declaring_property_class);
|
||||
|
||||
$property_storage = null;
|
||||
|
||||
if (isset($declaring_class_storage->properties[$prop_name])) {
|
||||
$property_storage = $declaring_class_storage->properties[$prop_name];
|
||||
|
||||
@ -763,15 +762,19 @@ class InstancePropertyAssignmentAnalyzer
|
||||
if (!$class_property_type) {
|
||||
$class_property_type = Type::getMixed();
|
||||
|
||||
if (!$assignment_value_type->hasMixed() && $property_storage) {
|
||||
if ($property_storage->suggested_type) {
|
||||
$property_storage->suggested_type = Type::combineUnionTypes(
|
||||
$source_analyzer = $statements_analyzer->getSource()->getSource();
|
||||
|
||||
if (!$assignment_value_type->hasMixed()
|
||||
&& $lhs_var_id === '$this'
|
||||
&& $source_analyzer instanceof ClassAnalyzer
|
||||
) {
|
||||
if (isset($source_analyzer->inferred_property_types[$prop_name])) {
|
||||
$source_analyzer->inferred_property_types[$prop_name] = Type::combineUnionTypes(
|
||||
$assignment_value_type,
|
||||
$property_storage->suggested_type
|
||||
$source_analyzer->inferred_property_types[$prop_name]
|
||||
);
|
||||
} else {
|
||||
$property_storage->suggested_type =
|
||||
$lhs_var_id === '$this' &&
|
||||
$source_analyzer->inferred_property_types[$prop_name] =
|
||||
($context->inside_constructor || $context->collect_initializations)
|
||||
? $assignment_value_type
|
||||
: Type::combineUnionTypes(Type::getNull(), $assignment_value_type);
|
||||
|
@ -4,6 +4,7 @@ namespace Psalm\Internal\Analyzer\Statements\Expression\Assignment;
|
||||
use PhpParser;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Stmt\PropertyProperty;
|
||||
use Psalm\Internal\Analyzer\ClassAnalyzer;
|
||||
use Psalm\Internal\Analyzer\ClassLikeAnalyzer;
|
||||
use Psalm\Internal\Analyzer\NamespaceAnalyzer;
|
||||
use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer;
|
||||
@ -173,8 +174,6 @@ class StaticPropertyAssignmentAnalyzer
|
||||
|
||||
$class_storage = $codebase->classlike_storage_provider->get($declaring_property_class);
|
||||
|
||||
$property_storage = $class_storage->properties[$prop_name->name];
|
||||
|
||||
if ($var_id) {
|
||||
$context->vars_in_scope[$var_id] = $assignment_value_type;
|
||||
}
|
||||
@ -189,14 +188,21 @@ class StaticPropertyAssignmentAnalyzer
|
||||
if (!$class_property_type) {
|
||||
$class_property_type = Type::getMixed();
|
||||
|
||||
if (!$assignment_value_type->hasMixed()) {
|
||||
if ($property_storage->suggested_type) {
|
||||
$property_storage->suggested_type = Type::combineUnionTypes(
|
||||
$source_analyzer = $statements_analyzer->getSource()->getSource();
|
||||
|
||||
$prop_name_name = $prop_name->name;
|
||||
|
||||
if (!$assignment_value_type->hasMixed()
|
||||
&& $source_analyzer instanceof ClassAnalyzer
|
||||
&& $fq_class_name === $source_analyzer->getFQCLN()
|
||||
) {
|
||||
if (isset($source_analyzer->inferred_property_types[$prop_name_name])) {
|
||||
$source_analyzer->inferred_property_types[$prop_name_name] = Type::combineUnionTypes(
|
||||
$assignment_value_type,
|
||||
$property_storage->suggested_type
|
||||
$source_analyzer->inferred_property_types[$prop_name_name]
|
||||
);
|
||||
} else {
|
||||
$property_storage->suggested_type = Type::combineUnionTypes(
|
||||
$source_analyzer->inferred_property_types[$prop_name_name] = Type::combineUnionTypes(
|
||||
Type::getNull(),
|
||||
$assignment_value_type
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user