From de1bb954cf2decb2a66fc33e65dab9dc11f3b278 Mon Sep 17 00:00:00 2001 From: orklah Date: Sun, 23 May 2021 22:24:29 +0200 Subject: [PATCH] Handle the case where a switch return on each case (#5819) * Handle the case where a switch return on each case * introduce a "hybrid" case exit type for cases where there's both "none" and something else --- .../Statements/Block/SwitchAnalyzer.php | 10 +++++++ .../ReturnTypeManipulationTest.php | 30 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/Psalm/Internal/Analyzer/Statements/Block/SwitchAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Block/SwitchAnalyzer.php index 1ef5d7c27..2865204dc 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Block/SwitchAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Block/SwitchAnalyzer.php @@ -87,6 +87,8 @@ class SwitchAnalyzer } elseif (in_array(ScopeAnalyzer::ACTION_LEAVE_SWITCH, $case_actions, true)) { $last_case_exit_type = 'break'; } + } elseif (count($case_actions) !== 1) { + $last_case_exit_type = 'hybrid'; } $case_exit_types[$i] = $last_case_exit_type; @@ -98,11 +100,16 @@ class SwitchAnalyzer $statements_analyzer->node_data->cache_assertions = false; + $all_options_returned = true; + for ($i = 0, $l = count($stmt->cases); $i < $l; $i++) { $case = $stmt->cases[$i]; /** @var string */ $case_exit_type = $case_exit_types[$i]; + if ($case_exit_type !== 'return_throw') { + $all_options_returned = false; + } $case_actions = $case_action_map[$i]; @@ -215,6 +222,9 @@ class SwitchAnalyzer $switch_scope->new_vars_possibly_in_scope ); + //a switch can't return in all options without a default + $context->has_returned = $all_options_returned && $has_default; + return null; } } diff --git a/tests/FileManipulation/ReturnTypeManipulationTest.php b/tests/FileManipulation/ReturnTypeManipulationTest.php index 3fc19169c..8ca900124 100644 --- a/tests/FileManipulation/ReturnTypeManipulationTest.php +++ b/tests/FileManipulation/ReturnTypeManipulationTest.php @@ -639,6 +639,36 @@ class ReturnTypeManipulationTest extends FileManipulationTestCase false, true, ], + 'switchReturn' => [ + ' + */ + function get_form_fields(string $a): array { + switch($a){ + default: + return []; + } + }', + '7.3', + ['MissingReturnType'], + false, + true, + ], ]; } }