From 75a3412a427a1072906f14854446ab2d64f7f1b3 Mon Sep 17 00:00:00 2001 From: Matthew Brown Date: Thu, 5 Mar 2020 21:24:08 -0500 Subject: [PATCH] Downgrade error when using unknown variable in mixed method --- .../Statements/Expression/CallAnalyzer.php | 14 ++++++++++++++ tests/UnusedCodeTest.php | 4 ++-- tests/UnusedVariableTest.php | 1 + 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php index e671db43869..9ed9e6d313d 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/CallAnalyzer.php @@ -30,6 +30,7 @@ use Psalm\Issue\PossiblyFalseArgument; use Psalm\Issue\PossiblyInvalidArgument; use Psalm\Issue\PossiblyNullArgument; +use Psalm\Issue\PossiblyUndefinedVariable; use Psalm\Issue\TooFewArguments; use Psalm\Issue\TooManyArguments; use Psalm\Issue\ArgumentTypeCoercion; @@ -706,6 +707,19 @@ private static function evaluateAribitraryParam( if (!$context->hasVariable($var_id, $statements_analyzer) || $context->vars_in_scope[$var_id]->isNull() ) { + if (!isset($context->vars_in_scope[$var_id])) { + if (IssueBuffer::accepts( + new PossiblyUndefinedVariable( + 'Variable ' . $var_id + . ' must be defined prior to use within an unknown function or method', + new CodeLocation($statements_analyzer->getSource(), $arg->value) + ), + $statements_analyzer->getSuppressedIssues() + )) { + // fall through + } + } + // 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; diff --git a/tests/UnusedCodeTest.php b/tests/UnusedCodeTest.php index a41287c1f0a..b7a78d7f498 100644 --- a/tests/UnusedCodeTest.php +++ b/tests/UnusedCodeTest.php @@ -543,14 +543,14 @@ class Foo { /** * @psalm-suppress MixedArgument */ - public function bar(): void { + public function bar(string $request): void { /** @var mixed $action */ $action = ""; $this->{"execute" . ucfirst($action)}($request); } } - (new Foo)->bar();' + (new Foo)->bar("request");' ], 'usedMethodCallForExternalMutationFreeClass' => [ 'passedByRef($b); }', ],