1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-27 04:45:20 +01:00

Move static property fetch analyzer to own class

This commit is contained in:
Brown 2020-06-18 11:53:24 -04:00
parent 98622783ec
commit f609a01497
11 changed files with 382 additions and 363 deletions

View File

@ -8,7 +8,7 @@ use Psalm\Internal\Analyzer\ClassLikeAnalyzer;
use Psalm\Internal\Analyzer\NamespaceAnalyzer;
use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer;
use Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier;
use Psalm\Internal\Analyzer\Statements\Expression\Fetch\PropertyFetchAnalyzer;
use Psalm\Internal\Analyzer\Statements\Expression\Fetch\InstancePropertyFetchAnalyzer;
use Psalm\Internal\Analyzer\StatementsAnalyzer;
use Psalm\Internal\Analyzer\TypeAnalyzer;
use Psalm\Internal\FileManipulation\FileManipulationBuffer;
@ -762,7 +762,7 @@ class PropertyAssignmentAnalyzer
if ($lhs_type_part instanceof Type\Atomic\TGenericObject) {
$class_storage = $codebase->classlike_storage_provider->get($fq_class_name);
$class_property_type = PropertyFetchAnalyzer::localizePropertyType(
$class_property_type = InstancePropertyFetchAnalyzer::localizePropertyType(
$codebase,
$class_property_type,
$lhs_type_part,

View File

@ -37,7 +37,6 @@ use function is_string;
use function strpos;
use function strtolower;
use function substr;
use function array_merge;
/**
* @internal

View File

@ -19,7 +19,6 @@ use Psalm\Issue\PossiblyNullOperand;
use Psalm\IssueBuffer;
use Psalm\Type;
use Psalm\Type\Atomic\TNamedObject;
use function array_merge;
use function strtolower;
use function strlen;

View File

@ -10,7 +10,6 @@ use Psalm\Issue\ImpureMethodCall;
use Psalm\IssueBuffer;
use Psalm\Type;
use Psalm\Type\Atomic\TNamedObject;
use function array_merge;
/**
* @internal

View File

@ -37,8 +37,6 @@ use Psalm\Type\Atomic\TList;
use function strtolower;
use function strpos;
use function explode;
use function in_array;
use Psalm\Issue\TaintedInput;
/**
* @internal

View File

@ -10,7 +10,6 @@ use Psalm\Internal\Analyzer\Statements\Expression\CallAnalyzer;
use Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentMapPopulator;
use Psalm\Internal\Analyzer\Statements\Expression\Call\ClassTemplateParamCollector;
use Psalm\Internal\Analyzer\Statements\Expression\Call\ArgumentsAnalyzer;
use Psalm\Internal\Analyzer\Statements\Expression\Fetch\PropertyFetchAnalyzer;
use Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier;
use Psalm\Internal\Analyzer\StatementsAnalyzer;
use Psalm\Internal\Analyzer\TypeAnalyzer;

View File

@ -57,7 +57,6 @@ use function strtolower;
use function in_array;
use function is_int;
use function preg_match;
use Psalm\Internal\Taint\TaintNode;
use Psalm\Internal\Taint\Source;
use Psalm\Internal\Type\TemplateResult;

View File

@ -9,7 +9,6 @@ use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer;
use Psalm\Internal\Analyzer\Statements\Expression\CallAnalyzer;
use Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier;
use Psalm\Internal\Analyzer\StatementsAnalyzer;
use Psalm\Internal\FileManipulation\FileManipulationBuffer;
use Psalm\Internal\Type\TemplateResult;
use Psalm\CodeLocation;
use Psalm\Context;
@ -20,7 +19,6 @@ use Psalm\Issue\MissingPropertyType;
use Psalm\Issue\MixedPropertyFetch;
use Psalm\Issue\NoInterfaceProperties;
use Psalm\Issue\NullPropertyFetch;
use Psalm\Issue\ParentNotFound;
use Psalm\Issue\PossiblyInvalidPropertyFetch;
use Psalm\Issue\PossiblyNullPropertyFetch;
use Psalm\Issue\UndefinedClass;
@ -41,16 +39,14 @@ use function strtolower;
use function array_values;
use function in_array;
use function array_keys;
use function count;
use function explode;
use Psalm\Internal\Taint\TaintNode;
/**
* @internal
*/
class PropertyFetchAnalyzer
class InstancePropertyFetchAnalyzer
{
public static function analyzeInstance(
public static function analyze(
StatementsAnalyzer $statements_analyzer,
PhpParser\Node\Expr\PropertyFetch $stmt,
Context $context
@ -1072,348 +1068,4 @@ class PropertyFetchAnalyzer
$type->parent_nodes = [$localized_property_node];
}
}
/**
* @param StatementsAnalyzer $statements_analyzer
* @param PhpParser\Node\Expr\StaticPropertyFetch $stmt
* @param Context $context
*/
public static function analyzeStatic(
StatementsAnalyzer $statements_analyzer,
PhpParser\Node\Expr\StaticPropertyFetch $stmt,
Context $context
) : bool {
if (!$stmt->class instanceof PhpParser\Node\Name) {
$old_data_provider = $statements_analyzer->node_data;
$statements_analyzer->node_data = clone $statements_analyzer->node_data;
$fake_instance_property = new PhpParser\Node\Expr\PropertyFetch(
$stmt->class,
$stmt->name,
$stmt->getAttributes()
);
$analysis_result = self::analyzeInstance($statements_analyzer, $fake_instance_property, $context);
$stmt_type = $statements_analyzer->node_data->getType($fake_instance_property);
$statements_analyzer->node_data = $old_data_provider;
$statements_analyzer->node_data->setType($stmt, $stmt_type ?: Type::getMixed());
return $analysis_result;
}
$fq_class_name = null;
$codebase = $statements_analyzer->getCodebase();
if (count($stmt->class->parts) === 1
&& in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true)
) {
if ($stmt->class->parts[0] === 'parent') {
$fq_class_name = $statements_analyzer->getParentFQCLN();
if ($fq_class_name === null) {
if (IssueBuffer::accepts(
new ParentNotFound(
'Cannot check property fetch on parent as this class does not extend another',
new CodeLocation($statements_analyzer->getSource(), $stmt)
),
$statements_analyzer->getSuppressedIssues()
)) {
return false;
}
return true;
}
} else {
$fq_class_name = (string)$context->self;
}
if ($context->isPhantomClass($fq_class_name)) {
return true;
}
} else {
$aliases = $statements_analyzer->getAliases();
if ($context->calling_method_id
&& !$stmt->class instanceof PhpParser\Node\Name\FullyQualified
) {
$codebase->file_reference_provider->addMethodReferenceToClassMember(
$context->calling_method_id,
'use:' . $stmt->class->parts[0] . ':' . \md5($statements_analyzer->getFilePath())
);
}
$fq_class_name = ClassLikeAnalyzer::getFQCLNFromNameObject(
$stmt->class,
$aliases
);
if ($context->isPhantomClass($fq_class_name)) {
return true;
}
if ($context->check_classes) {
if (ClassLikeAnalyzer::checkFullyQualifiedClassLikeName(
$statements_analyzer,
$fq_class_name,
new CodeLocation($statements_analyzer->getSource(), $stmt->class),
$context->self,
$context->calling_method_id,
$statements_analyzer->getSuppressedIssues(),
false
) !== true) {
return false;
}
}
}
if ($fq_class_name
&& $codebase->methods_to_move
&& $context->calling_method_id
&& isset($codebase->methods_to_move[$context->calling_method_id])
) {
$destination_method_id = $codebase->methods_to_move[$context->calling_method_id];
$codebase->classlikes->airliftClassLikeReference(
$fq_class_name,
explode('::', $destination_method_id)[0],
$statements_analyzer->getFilePath(),
(int) $stmt->class->getAttribute('startFilePos'),
(int) $stmt->class->getAttribute('endFilePos') + 1
);
}
if ($fq_class_name) {
$statements_analyzer->node_data->setType(
$stmt->class,
new Type\Union([new TNamedObject($fq_class_name)])
);
}
if ($stmt->name instanceof PhpParser\Node\VarLikeIdentifier) {
$prop_name = $stmt->name->name;
} elseif (($stmt_name_type = $statements_analyzer->node_data->getType($stmt->name))
&& $stmt_name_type->isSingleStringLiteral()
) {
$prop_name = $stmt_name_type->getSingleStringLiteral()->value;
} else {
$prop_name = null;
}
if (!$prop_name) {
if ($fq_class_name) {
$codebase->analyzer->addMixedMemberName(
strtolower($fq_class_name) . '::$',
$context->calling_method_id ?: $statements_analyzer->getFileName()
);
}
return true;
}
if (!$fq_class_name
|| !$context->check_classes
|| !$context->check_variables
|| ExpressionAnalyzer::isMock($fq_class_name)
) {
return true;
}
$var_id = ExpressionIdentifier::getVarId(
$stmt,
$context->self ?: $statements_analyzer->getFQCLN(),
$statements_analyzer
);
$property_id = $fq_class_name . '::$' . $prop_name;
if ($codebase->store_node_types
&& !$context->collect_initializations
&& !$context->collect_mutations
) {
$codebase->analyzer->addNodeReference(
$statements_analyzer->getFilePath(),
$stmt->name,
$property_id
);
}
if ($context->mutation_free) {
if (IssueBuffer::accepts(
new \Psalm\Issue\ImpureStaticProperty(
'Cannot use a static property in a mutation-free context',
new CodeLocation($statements_analyzer, $stmt)
),
$statements_analyzer->getSuppressedIssues()
)) {
// fall through
}
}
if ($var_id && $context->hasVariable($var_id, $statements_analyzer)) {
$stmt_type = $context->vars_in_scope[$var_id];
// we don't need to check anything
$statements_analyzer->node_data->setType($stmt, $stmt_type);
if ($codebase->collect_references) {
// log the appearance
$codebase->properties->propertyExists(
$property_id,
true,
$statements_analyzer,
$context,
$codebase->collect_locations
? new CodeLocation($statements_analyzer->getSource(), $stmt)
: null
);
}
if ($codebase->store_node_types
&& !$context->collect_initializations
&& !$context->collect_mutations
&& ($stmt_type = $statements_analyzer->node_data->getType($stmt))
) {
$codebase->analyzer->addNodeType(
$statements_analyzer->getFilePath(),
$stmt->name,
$stmt_type->getId()
);
}
return true;
}
if (!$codebase->properties->propertyExists(
$property_id,
true,
$statements_analyzer,
$context,
$codebase->collect_locations
? new CodeLocation($statements_analyzer->getSource(), $stmt)
: null
)
) {
if ($context->inside_isset) {
return true;
}
if (IssueBuffer::accepts(
new UndefinedPropertyFetch(
'Static property ' . $property_id . ' is not defined',
new CodeLocation($statements_analyzer->getSource(), $stmt),
$property_id
),
$statements_analyzer->getSuppressedIssues()
)) {
// fall through
}
return true;
}
if (ClassLikeAnalyzer::checkPropertyVisibility(
$property_id,
$context,
$statements_analyzer,
new CodeLocation($statements_analyzer->getSource(), $stmt),
$statements_analyzer->getSuppressedIssues()
) === false) {
return false;
}
$declaring_property_class = $codebase->properties->getDeclaringClassForProperty(
$fq_class_name . '::$' . $prop_name,
true,
$statements_analyzer
);
if ($declaring_property_class === null) {
return false;
}
$declaring_property_id = strtolower($declaring_property_class) . '::$' . $prop_name;
if ($codebase->alter_code) {
$moved_class = $codebase->classlikes->handleClassLikeReferenceInMigration(
$codebase,
$statements_analyzer,
$stmt->class,
$fq_class_name,
$context->calling_method_id
);
if (!$moved_class) {
foreach ($codebase->property_transforms as $original_pattern => $transformation) {
if ($declaring_property_id === $original_pattern) {
list($old_declaring_fq_class_name) = explode('::$', $declaring_property_id);
list($new_fq_class_name, $new_property_name) = explode('::$', $transformation);
$file_manipulations = [];
if (strtolower($new_fq_class_name) !== strtolower($old_declaring_fq_class_name)) {
$file_manipulations[] = new \Psalm\FileManipulation(
(int) $stmt->class->getAttribute('startFilePos'),
(int) $stmt->class->getAttribute('endFilePos') + 1,
Type::getStringFromFQCLN(
$new_fq_class_name,
$statements_analyzer->getNamespace(),
$statements_analyzer->getAliasedClassesFlipped(),
null
)
);
}
$file_manipulations[] = new \Psalm\FileManipulation(
(int) $stmt->name->getAttribute('startFilePos'),
(int) $stmt->name->getAttribute('endFilePos') + 1,
'$' . $new_property_name
);
FileManipulationBuffer::add($statements_analyzer->getFilePath(), $file_manipulations);
}
}
}
}
$class_storage = $codebase->classlike_storage_provider->get($declaring_property_class);
$property = $class_storage->properties[$prop_name];
if ($var_id) {
if ($property->type) {
$context->vars_in_scope[$var_id] = \Psalm\Internal\Type\TypeExpander::expandUnion(
$codebase,
clone $property->type,
$class_storage->name,
$class_storage->name,
$class_storage->parent_class
);
} else {
$context->vars_in_scope[$var_id] = Type::getMixed();
}
$stmt_type = clone $context->vars_in_scope[$var_id];
$statements_analyzer->node_data->setType($stmt, $stmt_type);
if ($codebase->store_node_types
&& !$context->collect_initializations
&& !$context->collect_mutations
) {
$codebase->analyzer->addNodeType(
$statements_analyzer->getFilePath(),
$stmt->name,
$stmt_type->getId()
);
}
} else {
$statements_analyzer->node_data->setType($stmt, Type::getMixed());
}
return true;
}
}

View File

@ -0,0 +1,374 @@
<?php
namespace Psalm\Internal\Analyzer\Statements\Expression\Fetch;
use PhpParser;
use Psalm\Internal\Analyzer\ClassLikeAnalyzer;
use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer;
use Psalm\Internal\Analyzer\Statements\Expression\ExpressionIdentifier;
use Psalm\Internal\Analyzer\StatementsAnalyzer;
use Psalm\Internal\FileManipulation\FileManipulationBuffer;
use Psalm\CodeLocation;
use Psalm\Context;
use Psalm\Issue\ParentNotFound;
use Psalm\Issue\UndefinedPropertyFetch;
use Psalm\IssueBuffer;
use Psalm\Type;
use Psalm\Type\Atomic\TNamedObject;
use function strtolower;
use function in_array;
use function count;
use function explode;
/**
* @internal
*/
class StaticPropertyFetchAnalyzer
{
/**
* @param StatementsAnalyzer $statements_analyzer
* @param PhpParser\Node\Expr\StaticPropertyFetch $stmt
* @param Context $context
*/
public static function analyze(
StatementsAnalyzer $statements_analyzer,
PhpParser\Node\Expr\StaticPropertyFetch $stmt,
Context $context
) : bool {
if (!$stmt->class instanceof PhpParser\Node\Name) {
$old_data_provider = $statements_analyzer->node_data;
$statements_analyzer->node_data = clone $statements_analyzer->node_data;
$fake_instance_property = new PhpParser\Node\Expr\PropertyFetch(
$stmt->class,
$stmt->name,
$stmt->getAttributes()
);
$analysis_result = InstancePropertyFetchAnalyzer::analyze(
$statements_analyzer,
$fake_instance_property,
$context
);
$stmt_type = $statements_analyzer->node_data->getType($fake_instance_property);
$statements_analyzer->node_data = $old_data_provider;
$statements_analyzer->node_data->setType($stmt, $stmt_type ?: Type::getMixed());
return $analysis_result;
}
$fq_class_name = null;
$codebase = $statements_analyzer->getCodebase();
if (count($stmt->class->parts) === 1
&& in_array(strtolower($stmt->class->parts[0]), ['self', 'static', 'parent'], true)
) {
if ($stmt->class->parts[0] === 'parent') {
$fq_class_name = $statements_analyzer->getParentFQCLN();
if ($fq_class_name === null) {
if (IssueBuffer::accepts(
new ParentNotFound(
'Cannot check property fetch on parent as this class does not extend another',
new CodeLocation($statements_analyzer->getSource(), $stmt)
),
$statements_analyzer->getSuppressedIssues()
)) {
return false;
}
return true;
}
} else {
$fq_class_name = (string)$context->self;
}
if ($context->isPhantomClass($fq_class_name)) {
return true;
}
} else {
$aliases = $statements_analyzer->getAliases();
if ($context->calling_method_id
&& !$stmt->class instanceof PhpParser\Node\Name\FullyQualified
) {
$codebase->file_reference_provider->addMethodReferenceToClassMember(
$context->calling_method_id,
'use:' . $stmt->class->parts[0] . ':' . \md5($statements_analyzer->getFilePath())
);
}
$fq_class_name = ClassLikeAnalyzer::getFQCLNFromNameObject(
$stmt->class,
$aliases
);
if ($context->isPhantomClass($fq_class_name)) {
return true;
}
if ($context->check_classes) {
if (ClassLikeAnalyzer::checkFullyQualifiedClassLikeName(
$statements_analyzer,
$fq_class_name,
new CodeLocation($statements_analyzer->getSource(), $stmt->class),
$context->self,
$context->calling_method_id,
$statements_analyzer->getSuppressedIssues(),
false
) !== true) {
return false;
}
}
}
if ($fq_class_name
&& $codebase->methods_to_move
&& $context->calling_method_id
&& isset($codebase->methods_to_move[$context->calling_method_id])
) {
$destination_method_id = $codebase->methods_to_move[$context->calling_method_id];
$codebase->classlikes->airliftClassLikeReference(
$fq_class_name,
explode('::', $destination_method_id)[0],
$statements_analyzer->getFilePath(),
(int) $stmt->class->getAttribute('startFilePos'),
(int) $stmt->class->getAttribute('endFilePos') + 1
);
}
if ($fq_class_name) {
$statements_analyzer->node_data->setType(
$stmt->class,
new Type\Union([new TNamedObject($fq_class_name)])
);
}
if ($stmt->name instanceof PhpParser\Node\VarLikeIdentifier) {
$prop_name = $stmt->name->name;
} elseif (($stmt_name_type = $statements_analyzer->node_data->getType($stmt->name))
&& $stmt_name_type->isSingleStringLiteral()
) {
$prop_name = $stmt_name_type->getSingleStringLiteral()->value;
} else {
$prop_name = null;
}
if (!$prop_name) {
if ($fq_class_name) {
$codebase->analyzer->addMixedMemberName(
strtolower($fq_class_name) . '::$',
$context->calling_method_id ?: $statements_analyzer->getFileName()
);
}
return true;
}
if (!$fq_class_name
|| !$context->check_classes
|| !$context->check_variables
|| ExpressionAnalyzer::isMock($fq_class_name)
) {
return true;
}
$var_id = ExpressionIdentifier::getVarId(
$stmt,
$context->self ?: $statements_analyzer->getFQCLN(),
$statements_analyzer
);
$property_id = $fq_class_name . '::$' . $prop_name;
if ($codebase->store_node_types
&& !$context->collect_initializations
&& !$context->collect_mutations
) {
$codebase->analyzer->addNodeReference(
$statements_analyzer->getFilePath(),
$stmt->name,
$property_id
);
}
if ($context->mutation_free) {
if (IssueBuffer::accepts(
new \Psalm\Issue\ImpureStaticProperty(
'Cannot use a static property in a mutation-free context',
new CodeLocation($statements_analyzer, $stmt)
),
$statements_analyzer->getSuppressedIssues()
)) {
// fall through
}
}
if ($var_id && $context->hasVariable($var_id, $statements_analyzer)) {
$stmt_type = $context->vars_in_scope[$var_id];
// we don't need to check anything
$statements_analyzer->node_data->setType($stmt, $stmt_type);
if ($codebase->collect_references) {
// log the appearance
$codebase->properties->propertyExists(
$property_id,
true,
$statements_analyzer,
$context,
$codebase->collect_locations
? new CodeLocation($statements_analyzer->getSource(), $stmt)
: null
);
}
if ($codebase->store_node_types
&& !$context->collect_initializations
&& !$context->collect_mutations
&& ($stmt_type = $statements_analyzer->node_data->getType($stmt))
) {
$codebase->analyzer->addNodeType(
$statements_analyzer->getFilePath(),
$stmt->name,
$stmt_type->getId()
);
}
return true;
}
if (!$codebase->properties->propertyExists(
$property_id,
true,
$statements_analyzer,
$context,
$codebase->collect_locations
? new CodeLocation($statements_analyzer->getSource(), $stmt)
: null
)
) {
if ($context->inside_isset) {
return true;
}
if (IssueBuffer::accepts(
new UndefinedPropertyFetch(
'Static property ' . $property_id . ' is not defined',
new CodeLocation($statements_analyzer->getSource(), $stmt),
$property_id
),
$statements_analyzer->getSuppressedIssues()
)) {
// fall through
}
return true;
}
if (ClassLikeAnalyzer::checkPropertyVisibility(
$property_id,
$context,
$statements_analyzer,
new CodeLocation($statements_analyzer->getSource(), $stmt),
$statements_analyzer->getSuppressedIssues()
) === false) {
return false;
}
$declaring_property_class = $codebase->properties->getDeclaringClassForProperty(
$fq_class_name . '::$' . $prop_name,
true,
$statements_analyzer
);
if ($declaring_property_class === null) {
return false;
}
$declaring_property_id = strtolower($declaring_property_class) . '::$' . $prop_name;
if ($codebase->alter_code) {
$moved_class = $codebase->classlikes->handleClassLikeReferenceInMigration(
$codebase,
$statements_analyzer,
$stmt->class,
$fq_class_name,
$context->calling_method_id
);
if (!$moved_class) {
foreach ($codebase->property_transforms as $original_pattern => $transformation) {
if ($declaring_property_id === $original_pattern) {
list($old_declaring_fq_class_name) = explode('::$', $declaring_property_id);
list($new_fq_class_name, $new_property_name) = explode('::$', $transformation);
$file_manipulations = [];
if (strtolower($new_fq_class_name) !== strtolower($old_declaring_fq_class_name)) {
$file_manipulations[] = new \Psalm\FileManipulation(
(int) $stmt->class->getAttribute('startFilePos'),
(int) $stmt->class->getAttribute('endFilePos') + 1,
Type::getStringFromFQCLN(
$new_fq_class_name,
$statements_analyzer->getNamespace(),
$statements_analyzer->getAliasedClassesFlipped(),
null
)
);
}
$file_manipulations[] = new \Psalm\FileManipulation(
(int) $stmt->name->getAttribute('startFilePos'),
(int) $stmt->name->getAttribute('endFilePos') + 1,
'$' . $new_property_name
);
FileManipulationBuffer::add($statements_analyzer->getFilePath(), $file_manipulations);
}
}
}
}
$class_storage = $codebase->classlike_storage_provider->get($declaring_property_class);
$property = $class_storage->properties[$prop_name];
if ($var_id) {
if ($property->type) {
$context->vars_in_scope[$var_id] = \Psalm\Internal\Type\TypeExpander::expandUnion(
$codebase,
clone $property->type,
$class_storage->name,
$class_storage->name,
$class_storage->parent_class
);
} else {
$context->vars_in_scope[$var_id] = Type::getMixed();
}
$stmt_type = clone $context->vars_in_scope[$var_id];
$statements_analyzer->node_data->setType($stmt, $stmt_type);
if ($codebase->store_node_types
&& !$context->collect_initializations
&& !$context->collect_mutations
) {
$codebase->analyzer->addNodeType(
$statements_analyzer->getFilePath(),
$stmt->name,
$stmt_type->getId()
);
}
} else {
$statements_analyzer->node_data->setType($stmt, Type::getMixed());
}
return true;
}
}

View File

@ -6,7 +6,7 @@ use Psalm\Internal\Analyzer\CommentAnalyzer;
use Psalm\Internal\Analyzer\FunctionLikeAnalyzer;
use Psalm\Internal\Analyzer\TraitAnalyzer;
use Psalm\Internal\Analyzer\Statements\ExpressionAnalyzer;
use Psalm\Internal\Analyzer\Statements\Expression\Fetch\PropertyFetchAnalyzer;
use Psalm\Internal\Analyzer\Statements\Expression\Fetch\InstancePropertyFetchAnalyzer;
use Psalm\Internal\Analyzer\StatementsAnalyzer;
use Psalm\CodeLocation;
use Psalm\Context;
@ -147,7 +147,7 @@ class YieldAnalyzer
if ($classlike_storage->yield) {
if ($expression_atomic_type instanceof Type\Atomic\TGenericObject) {
$yield_candidate_type = PropertyFetchAnalyzer::localizePropertyType(
$yield_candidate_type = InstancePropertyFetchAnalyzer::localizePropertyType(
$codebase,
clone $classlike_storage->yield,
$expression_atomic_type,

View File

@ -202,7 +202,7 @@ class ExpressionAnalyzer
}
if ($stmt instanceof PhpParser\Node\Expr\PropertyFetch) {
return Expression\Fetch\PropertyFetchAnalyzer::analyzeInstance(
return Expression\Fetch\InstancePropertyFetchAnalyzer::analyze(
$statements_analyzer,
$stmt,
$context
@ -210,7 +210,7 @@ class ExpressionAnalyzer
}
if ($stmt instanceof PhpParser\Node\Expr\StaticPropertyFetch) {
return Expression\Fetch\PropertyFetchAnalyzer::analyzeStatic(
return Expression\Fetch\StaticPropertyFetchAnalyzer::analyze(
$statements_analyzer,
$stmt,
$context