mirror of
https://github.com/danog/psalm.git
synced 2024-12-03 10:07:52 +01:00
Add comments to AtomicMethodCallAnalyzer and suppress ComplexMethod
This commit is contained in:
parent
257f67d593
commit
1d6338e13b
@ -36,6 +36,8 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
|
|||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param Type\Atomic\TNamedObject|Type\Atomic\TTemplateParam $static_type
|
* @param Type\Atomic\TNamedObject|Type\Atomic\TTemplateParam $static_type
|
||||||
|
*
|
||||||
|
* @psalm-suppress ComplexMethod it's really complex, but unavoidably so
|
||||||
*/
|
*/
|
||||||
public static function analyze(
|
public static function analyze(
|
||||||
StatementsAnalyzer $statements_analyzer,
|
StatementsAnalyzer $statements_analyzer,
|
||||||
@ -183,6 +185,7 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
|
|||||||
|
|
||||||
$naive_method_id = $method_id;
|
$naive_method_id = $method_id;
|
||||||
|
|
||||||
|
// this tells us whether or not we can stay on the happy path
|
||||||
$naive_method_exists = $codebase->methods->methodExists(
|
$naive_method_exists = $codebase->methods->methodExists(
|
||||||
$method_id,
|
$method_id,
|
||||||
$context->calling_method_id,
|
$context->calling_method_id,
|
||||||
@ -199,9 +202,9 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
|
|||||||
|
|
||||||
$fake_method_exists = false;
|
$fake_method_exists = false;
|
||||||
|
|
||||||
if (!$naive_method_exists
|
if (!$naive_method_exists) {
|
||||||
&& $codebase->methods->existence_provider->has($fq_class_name)
|
// if the method doesn't exist we check for any method existence providers
|
||||||
) {
|
if ($codebase->methods->existence_provider->has($fq_class_name)) {
|
||||||
$method_exists = $codebase->methods->existence_provider->doesMethodExist(
|
$method_exists = $codebase->methods->existence_provider->doesMethodExist(
|
||||||
$fq_class_name,
|
$fq_class_name,
|
||||||
$method_id->method_name,
|
$method_id->method_name,
|
||||||
@ -214,9 +217,32 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$naive_method_exists) {
|
$naive_method_exists = false;
|
||||||
|
|
||||||
|
// @mixin attributes are an absolute pain! Lots of complexity here,
|
||||||
|
// as they can redefine the called class, method id etc.
|
||||||
|
if ($class_storage->templatedMixins
|
||||||
|
&& $lhs_type_part instanceof Type\Atomic\TGenericObject
|
||||||
|
&& $class_storage->template_types
|
||||||
|
) {
|
||||||
[$lhs_type_part, $class_storage, $naive_method_exists, $method_id, $fq_class_name]
|
[$lhs_type_part, $class_storage, $naive_method_exists, $method_id, $fq_class_name]
|
||||||
= self::handleMixins(
|
= self::handleTemplatedMixins(
|
||||||
|
$class_storage,
|
||||||
|
$lhs_type_part,
|
||||||
|
$method_name_lc,
|
||||||
|
$codebase,
|
||||||
|
$context,
|
||||||
|
$method_id,
|
||||||
|
$source,
|
||||||
|
$stmt,
|
||||||
|
$statements_analyzer,
|
||||||
|
$fq_class_name
|
||||||
|
);
|
||||||
|
} elseif ($class_storage->mixin_declaring_fqcln
|
||||||
|
&& $class_storage->namedMixins
|
||||||
|
) {
|
||||||
|
[$lhs_type_part, $class_storage, $naive_method_exists, $method_id, $fq_class_name]
|
||||||
|
= self::handleRegularMixins(
|
||||||
$class_storage,
|
$class_storage,
|
||||||
$lhs_type_part,
|
$lhs_type_part,
|
||||||
$method_name_lc,
|
$method_name_lc,
|
||||||
@ -230,10 +256,12 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
|
|||||||
$lhs_var_id
|
$lhs_var_id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$all_intersection_return_type = null;
|
$all_intersection_return_type = null;
|
||||||
$all_intersection_existent_method_ids = [];
|
$all_intersection_existent_method_ids = [];
|
||||||
|
|
||||||
|
// insersection types are also fun, they also complicate matters
|
||||||
if ($intersection_types) {
|
if ($intersection_types) {
|
||||||
[$all_intersection_return_type, $all_intersection_existent_method_ids]
|
[$all_intersection_return_type, $all_intersection_existent_method_ids]
|
||||||
= self::getIntersectionReturnType(
|
= self::getIntersectionReturnType(
|
||||||
@ -314,14 +342,6 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$source_source = $statements_analyzer->getSource();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var \Psalm\Internal\Analyzer\ClassLikeAnalyzer|null
|
|
||||||
*/
|
|
||||||
$classlike_source = $source_source->getSource();
|
|
||||||
$classlike_source_fqcln = $classlike_source ? $classlike_source->getFQCLN() : null;
|
|
||||||
|
|
||||||
$intersection_method_id = $intersection_types
|
$intersection_method_id = $intersection_types
|
||||||
? '(' . $lhs_type_part . ')' . '::' . $stmt->name->name
|
? '(' . $lhs_type_part . ')' . '::' . $stmt->name->name
|
||||||
: null;
|
: null;
|
||||||
@ -329,7 +349,6 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
|
|||||||
|
|
||||||
if ($lhs_var_id === '$this'
|
if ($lhs_var_id === '$this'
|
||||||
&& $context->self
|
&& $context->self
|
||||||
&& $classlike_source_fqcln
|
|
||||||
&& $fq_class_name !== $context->self
|
&& $fq_class_name !== $context->self
|
||||||
&& $codebase->methods->methodExists(
|
&& $codebase->methods->methodExists(
|
||||||
new MethodIdentifier($context->self, $method_name_lc)
|
new MethodIdentifier($context->self, $method_name_lc)
|
||||||
@ -340,12 +359,6 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
|
|||||||
$fq_class_name = $context->self;
|
$fq_class_name = $context->self;
|
||||||
}
|
}
|
||||||
|
|
||||||
$is_interface = false;
|
|
||||||
|
|
||||||
if ($codebase->interfaceExists($fq_class_name)) {
|
|
||||||
$is_interface = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$source_method_id = $source instanceof FunctionLikeAnalyzer
|
$source_method_id = $source instanceof FunctionLikeAnalyzer
|
||||||
? $source->getId()
|
? $source->getId()
|
||||||
: null;
|
: null;
|
||||||
@ -369,7 +382,7 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
|
|||||||
$codebase,
|
$codebase,
|
||||||
$stmt,
|
$stmt,
|
||||||
$method_id,
|
$method_id,
|
||||||
$is_interface,
|
$codebase->interfaceExists($fq_class_name),
|
||||||
$context,
|
$context,
|
||||||
$codebase->config,
|
$codebase->config,
|
||||||
$all_intersection_return_type,
|
$all_intersection_return_type,
|
||||||
@ -623,7 +636,7 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
|
|||||||
* @param lowercase-string $method_name_lc
|
* @param lowercase-string $method_name_lc
|
||||||
* @return array{Type\Atomic\TNamedObject, \Psalm\Storage\ClassLikeStorage, bool, MethodIdentifier, string}
|
* @return array{Type\Atomic\TNamedObject, \Psalm\Storage\ClassLikeStorage, bool, MethodIdentifier, string}
|
||||||
*/
|
*/
|
||||||
private static function handleMixins(
|
private static function handleTemplatedMixins(
|
||||||
\Psalm\Storage\ClassLikeStorage $class_storage,
|
\Psalm\Storage\ClassLikeStorage $class_storage,
|
||||||
Type\Atomic\TNamedObject $lhs_type_part,
|
Type\Atomic\TNamedObject $lhs_type_part,
|
||||||
string $method_name_lc,
|
string $method_name_lc,
|
||||||
@ -633,8 +646,7 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
|
|||||||
\Psalm\StatementsSource $source,
|
\Psalm\StatementsSource $source,
|
||||||
PhpParser\Node\Expr\MethodCall $stmt,
|
PhpParser\Node\Expr\MethodCall $stmt,
|
||||||
StatementsAnalyzer $statements_analyzer,
|
StatementsAnalyzer $statements_analyzer,
|
||||||
string $fq_class_name,
|
string $fq_class_name
|
||||||
?string $lhs_var_id
|
|
||||||
) {
|
) {
|
||||||
$naive_method_exists = false;
|
$naive_method_exists = false;
|
||||||
|
|
||||||
@ -695,9 +707,36 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($class_storage->mixin_declaring_fqcln
|
}
|
||||||
&& $class_storage->namedMixins
|
|
||||||
|
return [
|
||||||
|
$lhs_type_part,
|
||||||
|
$class_storage,
|
||||||
|
$naive_method_exists,
|
||||||
|
$method_id,
|
||||||
|
$fq_class_name
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param lowercase-string $method_name_lc
|
||||||
|
* @return array{Type\Atomic\TNamedObject, \Psalm\Storage\ClassLikeStorage, bool, MethodIdentifier, string}
|
||||||
|
*/
|
||||||
|
private static function handleRegularMixins(
|
||||||
|
\Psalm\Storage\ClassLikeStorage $class_storage,
|
||||||
|
Type\Atomic\TNamedObject $lhs_type_part,
|
||||||
|
string $method_name_lc,
|
||||||
|
Codebase $codebase,
|
||||||
|
Context $context,
|
||||||
|
MethodIdentifier $method_id,
|
||||||
|
\Psalm\StatementsSource $source,
|
||||||
|
PhpParser\Node\Expr\MethodCall $stmt,
|
||||||
|
StatementsAnalyzer $statements_analyzer,
|
||||||
|
string $fq_class_name,
|
||||||
|
?string $lhs_var_id
|
||||||
) {
|
) {
|
||||||
|
$naive_method_exists = false;
|
||||||
|
|
||||||
foreach ($class_storage->namedMixins as $mixin) {
|
foreach ($class_storage->namedMixins as $mixin) {
|
||||||
if (!$class_storage->mixin_declaring_fqcln) {
|
if (!$class_storage->mixin_declaring_fqcln) {
|
||||||
continue;
|
continue;
|
||||||
@ -766,7 +805,6 @@ class AtomicMethodCallAnalyzer extends CallAnalyzer
|
|||||||
$method_id = $new_method_id;
|
$method_id = $new_method_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
$lhs_type_part,
|
$lhs_type_part,
|
||||||
|
Loading…
Reference in New Issue
Block a user