1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-30 04:39:00 +01:00

Fix checks for existing vars used in by-ref assignments

This commit is contained in:
Matthew Brown 2019-03-03 18:21:12 -05:00
parent 9e8c3b8c6e
commit a31420be5b
4 changed files with 27 additions and 6 deletions

View File

@ -977,8 +977,12 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer implements Statements
/** /**
* @return void * @return void
*/ */
public function examineParamTypes(StatementsAnalyzer $statements_analyzer, Context $context, Codebase $codebase) public function examineParamTypes(
{ StatementsAnalyzer $statements_analyzer,
Context $context,
Codebase $codebase,
PhpParser\Node $stmt = null
) {
if ($context->infer_types) { if ($context->infer_types) {
foreach ($context->possible_param_types as $var_id => $type) { foreach ($context->possible_param_types as $var_id => $type) {
if (isset($this->possible_param_types[$var_id])) { if (isset($this->possible_param_types[$var_id])) {
@ -1019,7 +1023,9 @@ abstract class FunctionLikeAnalyzer extends SourceAnalyzer implements Statements
. ' because it is passed by reference, ' . ' because it is passed by reference, '
. $actual_type->getId() . ' type found. Use @param-out to specify ' . $actual_type->getId() . ' type found. Use @param-out to specify '
. 'a different output type', . 'a different output type',
$param->location $stmt
? new CodeLocation($this, $stmt )
: $param->location
), ),
$statements_analyzer->getSuppressedIssues() $statements_analyzer->getSuppressedIssues()
)) { )) {

View File

@ -703,7 +703,7 @@ class ExpressionAnalyzer
); );
if ($existing_type->getId() !== 'array<empty, empty>') { if ($existing_type->getId() !== 'array<empty, empty>') {
$context->vars_in_scope[$var_id] = clone $by_ref_type; $context->vars_in_scope[$var_id] = clone $by_ref_out_type;
if (!isset($stmt->inferredType) || $stmt->inferredType->isEmpty()) { if (!isset($stmt->inferredType) || $stmt->inferredType->isEmpty()) {
$stmt->inferredType = clone $by_ref_type; $stmt->inferredType = clone $by_ref_type;
@ -1295,7 +1295,7 @@ class ExpressionAnalyzer
if ($source instanceof FunctionLikeAnalyzer if ($source instanceof FunctionLikeAnalyzer
&& !($source->getSource() instanceof TraitAnalyzer) && !($source->getSource() instanceof TraitAnalyzer)
) { ) {
$source->examineParamTypes($statements_analyzer, $context, $codebase); $source->examineParamTypes($statements_analyzer, $context, $codebase, $stmt);
$storage = $source->getFunctionLikeStorage($statements_analyzer); $storage = $source->getFunctionLikeStorage($statements_analyzer);

View File

@ -124,7 +124,7 @@ class ReturnAnalyzer
$context $context
); );
$source->examineParamTypes($statements_analyzer, $context, $codebase); $source->examineParamTypes($statements_analyzer, $context, $codebase, $stmt);
$storage = $source->getFunctionLikeStorage($statements_analyzer); $storage = $source->getFunctionLikeStorage($statements_analyzer);

View File

@ -116,6 +116,21 @@ class ReferenceConstraintTest extends TestCase
'$a' => 'int', '$a' => 'int',
], ],
], ],
'paramOutReturn' => [
'<?php
/**
* @param-out bool $s
*/
function foo(?bool &$s) : void {
$s = true;
}
$b = false;
foo($b);',
'assertions' => [
'$b' => 'bool',
],
],
]; ];
} }