Skip to content
Permalink
Browse files

Add support for tracking callables

  • Loading branch information...
muglug committed Apr 17, 2019
1 parent ac56256 commit a529f74473e25e0011abc103cff48dfbc1fbade9
@@ -2146,6 +2146,38 @@ public static function checkFunctionArgumentType(
$to_string_cast
);
if ($type_match_found
&& $param_type->hasCallableType()
) {
$potential_method_ids = [];
foreach ($input_type->getTypes() as $input_type_part) {
if ($input_type_part instanceof Type\Atomic\ObjectLike) {
$potential_method_id = TypeAnalyzer::getCallableMethodIdFromObjectLike(
$input_type_part
);
if ($potential_method_id) {
$potential_method_ids[] = $potential_method_id;
}
} elseif ($input_type_part instanceof Type\Atomic\TLiteralString) {
$potential_method_ids[] = $input_type_part->value;
}
}
foreach ($potential_method_ids as $potential_method_id) {
if (strpos($potential_method_id, '::')) {
$codebase->methods->methodExists(
$potential_method_id,
$context->calling_method_id,
null,
$statements_analyzer,
$statements_analyzer->getFilePath()
);
}
}
}
if ($context->strict_types
&& !$input_type->hasArray()
&& !$param_type->from_docblock
@@ -1361,7 +1361,7 @@ public static function getCallableFromAtomic(Codebase $codebase, Type\Atomic $in
}
/** @return ?string */
private static function getCallableMethodIdFromObjectLike(ObjectLike $input_type_part)
public static function getCallableMethodIdFromObjectLike(ObjectLike $input_type_part)
{
if (!isset($input_type_part->properties[0])
|| !isset($input_type_part->properties[1])
@@ -122,7 +122,11 @@ public function methodExists(
$fq_class_name = $this->classlikes->getUnAliasedName($fq_class_name);
$class_storage = $this->classlike_storage_provider->get($fq_class_name);
try {
$class_storage = $this->classlike_storage_provider->get($fq_class_name);
} catch (\InvalidArgumentException $e) {
return false;
}
if (isset($class_storage->declaring_method_ids[$method_name])) {
$declaring_method_id = $class_storage->declaring_method_ids[$method_name];
@@ -508,6 +508,14 @@ public function hasArray()
return isset($this->types['array']);
}
/**
* @return bool
*/
public function hasCallableType()
{
return isset($this->types['callable']) || isset($this->types['Closure']);
}
/**
* @return bool
*/
@@ -335,6 +335,18 @@ protected function inner(): void {
$myFooBar = new MyFooBar();
$myFooBar->doIt();',
],
'methodUsedAsCallable' => [
'<?php
class C {
public static function foo() : void {}
}
function takesCallable(callable $c) : void {
$c();
}
takesCallable([C::class, "foo"]);',
],
];
}

0 comments on commit a529f74

Please sign in to comment.
You can’t perform that action at this time.