1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 20:34:47 +01:00

fix #2125 - Don’t assume function args are necessarily authoratative

This commit is contained in:
Brown 2019-09-11 13:52:37 -04:00
parent a8e58b0ba0
commit 944531b73b
3 changed files with 47 additions and 6 deletions

View File

@ -1244,7 +1244,8 @@ class CallAnalyzer
$existing_generic_params,
$generic_params,
$template_types,
$function_storage ? $function_storage->pure : false
$function_storage ? $function_storage->pure : false,
$in_call_map
) === false) {
return false;
}
@ -1382,9 +1383,10 @@ class CallAnalyzer
PhpParser\Node\Arg $arg,
Context $context,
array $existing_generic_params,
array &$generic_params = null,
array $template_types = null,
bool $function_is_pure
?array &$generic_params,
?array $template_types,
bool $function_is_pure,
bool $in_call_map
) {
$codebase = $statements_analyzer->getCodebase();
@ -1449,7 +1451,8 @@ class CallAnalyzer
$existing_generic_params,
$generic_params,
$template_types,
$function_is_pure
$function_is_pure,
$in_call_map
) === false) {
return false;
}
@ -1612,7 +1615,8 @@ class CallAnalyzer
?array $existing_generic_params,
?array &$generic_params,
?array $template_types,
bool $function_is_pure
bool $function_is_pure,
bool $in_call_map
) {
if (!$function_param->type) {
if (!$codebase->infer_types_from_usage) {
@ -1771,6 +1775,7 @@ class CallAnalyzer
$function_param,
$arg->unpack,
$function_is_pure,
$in_call_map,
$function_location
) === false) {
return false;
@ -2277,6 +2282,7 @@ class CallAnalyzer
FunctionLikeParameter $function_param,
bool $unpack,
bool $function_is_pure,
bool $in_call_map,
CodeLocation $function_location
) {
$codebase = $statements_analyzer->getCodebase();
@ -2353,6 +2359,7 @@ class CallAnalyzer
if (!$function_param->by_ref
&& !($function_param->is_variadic xor $unpack)
&& $cased_method_id !== 'echo'
&& (!$in_call_map || $context->strict_types)
) {
self::coerceValueAfterGatekeeperArgument(
$statements_analyzer,
@ -2769,6 +2776,7 @@ class CallAnalyzer
&& !$function_param->by_ref
&& !($function_param->is_variadic xor $unpack)
&& $cased_method_id !== 'echo'
&& (!$in_call_map || $context->strict_types)
) {
self::coerceValueAfterGatekeeperArgument(
$statements_analyzer,

View File

@ -568,6 +568,7 @@ class StatementsAnalyzer extends SourceAnalyzer implements StatementsSource
$context,
$echo_param,
false,
false,
true,
new CodeLocation($this->source, $stmt)
) === false) {
@ -620,6 +621,7 @@ class StatementsAnalyzer extends SourceAnalyzer implements StatementsSource
) {
$function_id = strtolower($stmt->name->name);
$function_context = new Context($context->self);
$function_context->strict_types = $context->strict_types;
$config = Config::getInstance();
$function_context->collect_references = $codebase->collect_references;
$function_context->collect_exceptions = $config->check_for_throws_docblock;

View File

@ -1858,6 +1858,20 @@ class FunctionCallTest extends TestCase
$a = print_r([], 1);
echo $a;',
],
'dontCoerceCallMapArgs' => [
'<?php
function getStr() : ?string {
return rand(0,1) ? "test" : null;
}
function test() : void {
$g = getStr();
/** @psalm-suppress PossiblyNullArgument */
$x = strtoupper($g);
$c = "prefix " . (strtoupper($g ?? "") === "x" ? "xa" : "ya");
echo "$x, $c\n";
}'
],
];
}
@ -2429,6 +2443,23 @@ class FunctionCallTest extends TestCase
}',
'error_message' => 'UndefinedVariable',
],
'coerceCallMapArgsInStrictMode' => [
'<?php
declare(strict_types=1);
function getStr() : ?string {
return rand(0,1) ? "test" : null;
}
function test() : void {
$g = getStr();
/** @psalm-suppress PossiblyNullArgument */
$x = strtoupper($g);
$c = "prefix " . (strtoupper($g ?? "") === "x" ? "xa" : "ya");
echo "$x, $c\n";
}',
'error_message' => 'TypeDoesNotContainType',
],
];
}
}