mirror of
https://github.com/danog/psalm.git
synced 2025-01-21 21:31:13 +01:00
Add check for array access on invalid type
This commit is contained in:
parent
e9ea66f21b
commit
05a004c8bc
@ -314,9 +314,9 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
|
||||
public function getMethodId()
|
||||
{
|
||||
if ($this->function instanceof ClassMethod) {
|
||||
$function_name = $this->function->name;
|
||||
$function_name = (string)$this->function->name;
|
||||
|
||||
if (strtolower($function_name) === strtolower($this->class_name)) {
|
||||
if (strtolower($function_name) === strtolower((string)$this->class_name)) {
|
||||
$function_name = '__construct';
|
||||
}
|
||||
|
||||
|
@ -172,12 +172,12 @@ class MethodChecker extends FunctionLikeChecker
|
||||
*/
|
||||
public static function extractReflectionMethodInfo(\ReflectionMethod $method)
|
||||
{
|
||||
if (strtolower($method->name) === strtolower((string)$method->class)) {
|
||||
if (strtolower((string)$method->name) === strtolower((string)$method->class)) {
|
||||
$method_id = $method->class . '::__construct';
|
||||
self::$cased_method_ids[$method_id] = $method->class . '::__construct';
|
||||
}
|
||||
else {
|
||||
$method_id = $method->class . '::' . strtolower($method->name);
|
||||
$method_id = $method->class . '::' . strtolower((string)$method->name);
|
||||
self::$cased_method_ids[$method_id] = $method->class . '::' . $method->name;
|
||||
}
|
||||
|
||||
|
@ -903,6 +903,21 @@ class FetchChecker
|
||||
}
|
||||
|
||||
$stmt->inferredType = Type::getString();
|
||||
} elseif ($type->isNull()) {
|
||||
// @todo emit NullArrayAccess issue
|
||||
} elseif ($type->isMixed()) {
|
||||
// @todo emit MixedArrayAccess issue
|
||||
} elseif ($type->value && !ClassChecker::classImplements($type->value, 'ArrayAccess')) {
|
||||
if (IssueBuffer::accepts(
|
||||
new InvalidArrayAccess(
|
||||
'Cannot access value on non-array variable ' . $var_id . ' of type ' . $var_type,
|
||||
$statements_checker->getCheckedFileName(),
|
||||
$stmt->getLine()
|
||||
),
|
||||
$statements_checker->getSuppressedIssues()
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -511,41 +511,6 @@ class StatementsChecker
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $call
|
||||
* @param PhpParser\Node\Arg[] $args
|
||||
* @param string $method_id
|
||||
* @return string|null
|
||||
*/
|
||||
protected static function getMethodFromCallBlock($call, array $args, $method_id)
|
||||
{
|
||||
$fq_class_name = explode('::', $method_id)[0];
|
||||
|
||||
$original_call = $call;
|
||||
|
||||
$call = preg_replace('/^\$this(->|::)/', $fq_class_name . '::', $call);
|
||||
|
||||
$call = preg_replace('/\(\)$/', '', $call);
|
||||
|
||||
if (strpos($call, '$') !== false) {
|
||||
$method_params = MethodChecker::getMethodParams($method_id);
|
||||
|
||||
foreach ($args as $i => $arg) {
|
||||
$method_param = $method_params[$i];
|
||||
$preg_var_name = preg_quote('$' . $method_param['name']);
|
||||
|
||||
if (preg_match('/::' . $preg_var_name . '$/', $call)) {
|
||||
if ($arg->value instanceof PhpParser\Node\Scalar\String_) {
|
||||
$call = preg_replace('/' . $preg_var_name . '$/', $arg->value->value, $call);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $original_call === $call || strpos($call, '$') !== false ? null : $call;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PhpParser\Node\Stmt\Const_ $stmt
|
||||
* @param Context $context
|
||||
|
Loading…
x
Reference in New Issue
Block a user