From 6cf2e31c4abba5ccd8d591d7e2ad5d655ec3164f Mon Sep 17 00:00:00 2001 From: adrew Date: Sat, 11 Dec 2021 23:37:15 +0300 Subject: [PATCH 1/3] Forbid positional arg after named arg --- .../Expression/Call/ArgumentsAnalyzer.php | 15 +++++++++++++++ tests/ArgTest.php | 14 ++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php index ac083fb1bfa..aede14414ea 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php @@ -23,6 +23,7 @@ use Psalm\Internal\Type\TemplateResult; use Psalm\Internal\Type\TemplateStandinTypeReplacer; use Psalm\Internal\Type\TypeExpander; +use Psalm\Issue\InvalidArgument; use Psalm\Issue\InvalidNamedArgument; use Psalm\Issue\InvalidPassByReference; use Psalm\Issue\PossiblyUndefinedVariable; @@ -646,8 +647,20 @@ public static function checkArgumentsMatch( $arg_function_params = []; $matched_args = []; + $named_args_was_used = false; foreach ($args as $argument_offset => $arg) { + if ($named_args_was_used && !$arg->name) { + IssueBuffer::maybeAdd( + new InvalidNamedArgument( + 'Cannot use positional argument after named argument', + new CodeLocation($statements_analyzer, $arg), + (string)$method_id + ), + $statements_analyzer->getSuppressedIssues() + ); + } + if ($arg->unpack) { if ($function_param_count > $argument_offset) { for ($i = $argument_offset; $i < $function_param_count; $i++) { @@ -712,6 +725,8 @@ public static function checkArgumentsMatch( } } } elseif ($arg->name && (!$function_storage || $function_storage->allow_named_arg_calls)) { + $named_args_was_used = true; + foreach ($function_params as $candidate_param) { if ($candidate_param->name === $arg->name->name || $candidate_param->is_variadic) { if ($candidate_param->name === $arg->name->name) { diff --git a/tests/ArgTest.php b/tests/ArgTest.php index 623ce95e977..69083756ed7 100644 --- a/tests/ArgTest.php +++ b/tests/ArgTest.php @@ -1,6 +1,7 @@ 'InvalidNamedArgument' ], + 'usePositionalArgAfterNamed' => [ + ' 'InvalidNamedArgument' + ], 'useUnpackedInvalidNamedArgument' => [ ' Date: Sat, 11 Dec 2021 23:45:34 +0300 Subject: [PATCH 2/3] Remove use of nonexistent class --- tests/ArgTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/ArgTest.php b/tests/ArgTest.php index 69083756ed7..259d7cb2f57 100644 --- a/tests/ArgTest.php +++ b/tests/ArgTest.php @@ -1,7 +1,6 @@ Date: Sun, 12 Dec 2021 01:58:45 +0200 Subject: [PATCH 3/3] Drop unused use --- .../Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php index aede14414ea..2503dbd60a2 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentsAnalyzer.php @@ -23,7 +23,6 @@ use Psalm\Internal\Type\TemplateResult; use Psalm\Internal\Type\TemplateStandinTypeReplacer; use Psalm\Internal\Type\TypeExpander; -use Psalm\Issue\InvalidArgument; use Psalm\Issue\InvalidNamedArgument; use Psalm\Issue\InvalidPassByReference; use Psalm\Issue\PossiblyUndefinedVariable;