1
0
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:
Brown 2020-07-07 19:32:44 -04:00
parent ee8619f7bb
commit 0034f2e4bd
3 changed files with 45 additions and 19 deletions

View File

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

View File

@ -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,16 +762,20 @@ 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' &&
($context->inside_constructor || $context->collect_initializations)
$source_analyzer->inferred_property_types[$prop_name] =
($context->inside_constructor || $context->collect_initializations)
? $assignment_value_type
: Type::combineUnionTypes(Type::getNull(), $assignment_value_type);
}

View File

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