From 086237aab70b3c3ca2b014560dbfda2cae9f0c84 Mon Sep 17 00:00:00 2001 From: Matt Brown Date: Fri, 13 Nov 2020 11:55:42 -0500 Subject: [PATCH] Fix #4544 - improve handling of get_class in match --- .../Statements/Expression/MatchAnalyzer.php | 54 +++++++++++++++---- tests/MatchTest.php | 22 ++++++++ 2 files changed, 65 insertions(+), 11 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/MatchAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/MatchAnalyzer.php index 46041df9f..55a428146 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/MatchAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/MatchAnalyzer.php @@ -47,22 +47,54 @@ class MatchAnalyzer $match_condition = $stmt->cond; - if (!$switch_var_id - && ($stmt->cond instanceof PhpParser\Node\Expr\FuncCall + if (!$switch_var_id) { + if ($stmt->cond instanceof PhpParser\Node\Expr\FuncCall + && $stmt->cond->name instanceof PhpParser\Node\Name + && ($stmt->cond->name->parts === ['get_class'] + || $stmt->cond->name->parts === ['gettype'] + || $stmt->cond->name->parts === ['get_debug_type']) + && $stmt->cond->args + ) { + $first_arg = $stmt->cond->args[0]; + + if (!$first_arg->value instanceof PhpParser\Node\Expr\Variable) { + $switch_var_id = '$__tmp_switch__' . (int) $first_arg->value->getAttribute('startFilePos'); + + $condition_type = $statements_analyzer->node_data->getType($first_arg->value) ?: Type::getMixed(); + + $context->vars_in_scope[$switch_var_id] = $condition_type; + + $match_condition = new PhpParser\Node\Expr\FuncCall( + $stmt->cond->name, + [ + new PhpParser\Node\Arg( + new PhpParser\Node\Expr\Variable( + substr($switch_var_id, 1), + $first_arg->value->getAttributes() + ), + false, + false, + $first_arg->getAttributes() + ) + ], + $stmt->cond->getAttributes() + ); + } + } elseif ($stmt->cond instanceof PhpParser\Node\Expr\FuncCall || $stmt->cond instanceof PhpParser\Node\Expr\MethodCall || $stmt->cond instanceof PhpParser\Node\Expr\StaticCall - ) - ) { - $switch_var_id = '$__tmp_switch__' . (int) $stmt->cond->getAttribute('startFilePos'); + ) { + $switch_var_id = '$__tmp_switch__' . (int) $stmt->cond->getAttribute('startFilePos'); - $condition_type = $statements_analyzer->node_data->getType($stmt->cond) ?: Type::getMixed(); + $condition_type = $statements_analyzer->node_data->getType($stmt->cond) ?: Type::getMixed(); - $context->vars_in_scope[$switch_var_id] = $condition_type; + $context->vars_in_scope[$switch_var_id] = $condition_type; - $match_condition = new PhpParser\Node\Expr\Variable( - substr($switch_var_id, 1), - $stmt->cond->getAttributes() - ); + $match_condition = new PhpParser\Node\Expr\Variable( + substr($switch_var_id, 1), + $stmt->cond->getAttributes() + ); + } } $arms = $stmt->arms; diff --git a/tests/MatchTest.php b/tests/MatchTest.php index d8e69bee6..745a0a8b1 100644 --- a/tests/MatchTest.php +++ b/tests/MatchTest.php @@ -56,6 +56,28 @@ class MatchTest extends TestCase [], '8.0' ], + 'getClassWithMethod' => [ + ' $value->hello(), + default => "b", + }; + }', + [], + [], + '8.0' + ], ]; }