1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 12:24:49 +01:00

Add error for pass by reference

This commit is contained in:
Matthew Brown 2017-09-16 13:16:21 -04:00
parent fc6b663c8a
commit 3a8efec728
4 changed files with 46 additions and 6 deletions

View File

@ -110,6 +110,7 @@
<xs:element name="InvalidIterator" type="IssueHandlerType" minOccurs="0" />
<xs:element name="InvalidMethodCall" type="IssueHandlerType" minOccurs="0" />
<xs:element name="InvalidOperand" type="IssueHandlerType" minOccurs="0" />
<xs:element name="InvalidPassByReference" type="IssueHandlerType" minOccurs="0" />
<xs:element name="InvalidPropertyAssignment" type="IssueHandlerType" minOccurs="0" />
<xs:element name="InvalidPropertyFetch" type="IssueHandlerType" minOccurs="0" />
<xs:element name="InvalidReturnType" type="IssueHandlerType" minOccurs="0" />

View File

@ -23,6 +23,7 @@ use Psalm\Issue\ImplicitToStringCast;
use Psalm\Issue\InvalidArgument;
use Psalm\Issue\InvalidFunctionCall;
use Psalm\Issue\InvalidMethodCall;
use Psalm\Issue\InvalidPassByReference;
use Psalm\Issue\InvalidScalarArgument;
use Psalm\Issue\InvalidScope;
use Psalm\Issue\MixedArgument;
@ -1697,11 +1698,29 @@ class CallChecker
}
foreach ($args as $argument_offset => $arg) {
if (isset($arg->value->inferredType)) {
$function_param = count($function_params) > $argument_offset
? $function_params[$argument_offset]
: ($last_param && $last_param->is_variadic ? $last_param : null);
$function_param = count($function_params) > $argument_offset
? $function_params[$argument_offset]
: ($last_param && $last_param->is_variadic ? $last_param : null);
if ($function_param
&& $function_param->by_ref
&& !($arg->value instanceof PhpParser\Node\Expr\Variable)
&& !($arg->value instanceof PhpParser\Node\Expr\PropertyFetch)
) {
if (IssueBuffer::accepts(
new InvalidPassByReference(
'Parameter ' . ($argument_offset + 1) . ' of ' . $method_id . ' expects a variable',
$code_location
),
$statements_checker->getSuppressedIssues()
)) {
return false;
}
break;
}
if (isset($arg->value->inferredType)) {
if ($function_param && $function_param->type) {
$param_type = clone $function_param->type;

View File

@ -0,0 +1,6 @@
<?php
namespace Psalm\Issue;
class InvalidPassByReference extends CodeError
{
}

View File

@ -266,6 +266,21 @@ class FunctionCallTest extends TestCase
foo($a3);',
],
'goodByRef' => [
'<?php
class A {
/** @var string */
public $foo = "hello";
}
$a = new A();
$b = "goodbye";
function fooFoo(string &$v) : void {}
fooFoo($a->foo);
fooFoo($b);',
],
];
}
@ -359,8 +374,7 @@ class FunctionCallTest extends TestCase
function f($p = false) {}',
'error_message' => 'InvalidParamDefault',
],
// Skipped. Does not throw an error.
'SKIPPED-badByRef' => [
'badByRef' => [
'<?php
function fooFoo(string &$v) : void {}
fooFoo("a");',