1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-22 05:41:20 +01:00

Revert "Fix #2909 - don’t treat args of unknown calls as possible by-reference vars"

This reverts commit 105fe012c4d177bbb23d81c73e9b1ea4c69fe7be.
This commit is contained in:
Matthew Brown 2020-03-05 21:10:29 -05:00
parent 09137b0a32
commit b2678d40aa
4 changed files with 59 additions and 27 deletions

View File

@ -656,6 +656,27 @@ class CallAnalyzer
StatementsAnalyzer $statements_analyzer,
PhpParser\Node\Arg $arg,
Context $context
) {
// there are a bunch of things we want to evaluate even when we don't
// know what function/method is being called
if ($arg->value instanceof PhpParser\Node\Expr\Closure
|| $arg->value instanceof PhpParser\Node\Expr\ConstFetch
|| $arg->value instanceof PhpParser\Node\Expr\ClassConstFetch
|| $arg->value instanceof PhpParser\Node\Expr\FuncCall
|| $arg->value instanceof PhpParser\Node\Expr\MethodCall
|| $arg->value instanceof PhpParser\Node\Expr\StaticCall
|| $arg->value instanceof PhpParser\Node\Expr\New_
|| $arg->value instanceof PhpParser\Node\Expr\Assign
|| $arg->value instanceof PhpParser\Node\Expr\ArrayDimFetch
|| $arg->value instanceof PhpParser\Node\Expr\PropertyFetch
|| $arg->value instanceof PhpParser\Node\Expr\Array_
|| $arg->value instanceof PhpParser\Node\Expr\BinaryOp
|| $arg->value instanceof PhpParser\Node\Expr\Ternary
|| $arg->value instanceof PhpParser\Node\Scalar\Encapsed
|| $arg->value instanceof PhpParser\Node\Expr\PostInc
|| $arg->value instanceof PhpParser\Node\Expr\PostDec
|| $arg->value instanceof PhpParser\Node\Expr\PreInc
|| $arg->value instanceof PhpParser\Node\Expr\PreDec
) {
$was_inside_call = $context->inside_call;
$context->inside_call = true;
@ -667,6 +688,7 @@ class CallAnalyzer
if (!$was_inside_call) {
$context->inside_call = false;
}
}
if ($arg->value instanceof PhpParser\Node\Expr\PropertyFetch
&& $arg->value->name instanceof PhpParser\Node\Identifier
@ -681,7 +703,27 @@ class CallAnalyzer
}
if ($var_id) {
if ($context->hasVariable($var_id, $statements_analyzer)) {
if (!$context->hasVariable($var_id, $statements_analyzer)
|| $context->vars_in_scope[$var_id]->isNull()
) {
// we don't know if it exists, assume it's passed by reference
$context->vars_in_scope[$var_id] = Type::getMixed();
$context->vars_possibly_in_scope[$var_id] = true;
if (strpos($var_id, '-') === false
&& strpos($var_id, '[') === false
&& !$statements_analyzer->hasVariable($var_id)
) {
$location = new CodeLocation($statements_analyzer, $arg->value);
$statements_analyzer->registerVariable(
$var_id,
$location,
null
);
$statements_analyzer->registerVariableUses([$location->getHash() => $location]);
}
} else {
$context->removeVarFromConflictingClauses(
$var_id,
$context->vars_in_scope[$var_id],

View File

@ -859,23 +859,6 @@ class MethodCallTest extends TestCase
}',
'error_message' => 'InvalidStringClass',
],
'dontAssumePossibleByRef' => [
'<?php
class C {
function b(string $p): string {
return $p;
}
}
/** @return mixed */
function func() {
return new C();
}
/** @psalm-suppress MixedMethodCall */
func()->b($param);',
'error_message' => 'UndefinedGlobalVariable',
],
];
}
}

View File

@ -543,14 +543,14 @@ class UnusedCodeTest extends TestCase
/**
* @psalm-suppress MixedArgument
*/
public function bar(string $request): void {
public function bar(): void {
/** @var mixed $action */
$action = "";
$this->{"execute" . ucfirst($action)}($request);
}
}
(new Foo)->bar("hello");'
(new Foo)->bar();'
],
'usedMethodCallForExternalMutationFreeClass' => [
'<?php

View File

@ -518,6 +518,13 @@ class UnusedVariableTest extends TestCase
if ($i) {}',
],
'unknownMethodCallWithVar' => [
'<?php
/** @psalm-suppress MixedMethodCall */
function passesByRef(object $a): void {
$a->passedByRef($b);
}',
],
'usedMethodCallVariable' => [
'<?php
function reindex(array $arr, string $methodName): array {