mirror of
https://github.com/danog/psalm.git
synced 2025-01-21 21:31:13 +01:00
Improve handling of property-mutating calls
This commit is contained in:
parent
2dc86651a4
commit
ccdb29abfa
@ -4,6 +4,7 @@ namespace Psalm\Internal\Analyzer\Statements\Expression\Call\Method;
|
||||
use PhpParser;
|
||||
use Psalm\Internal\Analyzer\ClassLikeAnalyzer;
|
||||
use Psalm\Internal\Analyzer\StatementsAnalyzer;
|
||||
use Psalm\Internal\Analyzer\Statements\Expression\Call\ClassTemplateParamCollector;
|
||||
use Psalm\Codebase;
|
||||
use Psalm\CodeLocation;
|
||||
use Psalm\Context;
|
||||
@ -145,16 +146,83 @@ class MethodCallPurityAnalyzer
|
||||
&& isset($context->vars_in_scope[$mutation_var_id])
|
||||
&& !isset($class_storage->declaring_property_ids[$name]);
|
||||
|
||||
$current_context = $context;
|
||||
|
||||
do {
|
||||
$current_context->remove($mutation_var_id);
|
||||
} while ($current_context = $current_context->parent_context);
|
||||
|
||||
if ($this_property_didnt_exist) {
|
||||
$context->vars_in_scope[$mutation_var_id] = Type::getMixed();
|
||||
} else {
|
||||
$context->vars_in_scope[$mutation_var_id] = self::getExpandedPropertyType(
|
||||
$codebase,
|
||||
$class_storage->name,
|
||||
$name,
|
||||
$class_storage
|
||||
) ?: Type::getMixed();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function getExpandedPropertyType(
|
||||
Codebase $codebase,
|
||||
string $fq_class_name,
|
||||
string $property_name,
|
||||
\Psalm\Storage\ClassLikeStorage $storage
|
||||
) : ?Type\Union {
|
||||
$property_class_name = $codebase->properties->getDeclaringClassForProperty(
|
||||
$fq_class_name . '::$' . $property_name,
|
||||
true
|
||||
);
|
||||
|
||||
if ($property_class_name === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$property_class_storage = $codebase->classlike_storage_provider->get($property_class_name);
|
||||
|
||||
$property_storage = $property_class_storage->properties[$property_name];
|
||||
|
||||
if (!$property_storage->type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$property_type = clone $property_storage->type;
|
||||
|
||||
$fleshed_out_type = !$property_type->isMixed()
|
||||
? \Psalm\Internal\Type\TypeExpander::expandUnion(
|
||||
$codebase,
|
||||
$property_type,
|
||||
$fq_class_name,
|
||||
$fq_class_name,
|
||||
$storage->parent_class,
|
||||
true,
|
||||
false,
|
||||
$storage->final
|
||||
)
|
||||
: $property_type;
|
||||
|
||||
$class_template_params = ClassTemplateParamCollector::collect(
|
||||
$codebase,
|
||||
$property_class_storage,
|
||||
$storage,
|
||||
null,
|
||||
new Type\Atomic\TNamedObject($fq_class_name),
|
||||
true
|
||||
);
|
||||
|
||||
$template_result = new \Psalm\Internal\Type\TemplateResult(
|
||||
$class_template_params ?: [],
|
||||
[]
|
||||
);
|
||||
|
||||
if ($class_template_params) {
|
||||
$fleshed_out_type = \Psalm\Internal\Type\TemplateStandinTypeReplacer::replace(
|
||||
$fleshed_out_type,
|
||||
$template_result,
|
||||
$codebase,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
return $fleshed_out_type;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user