|
9 | 9 | use PhpParser\Node\Expr\MethodCall; |
10 | 10 | use PhpParser\Node\Expr\New_; |
11 | 11 | use PhpParser\Node\Name\FullyQualified; |
| 12 | +use PHPStan\Analyser\ArgumentsNormalizer; |
12 | 13 | use PHPStan\Analyser\Scope; |
| 14 | +use PHPStan\Reflection\ParametersAcceptorSelector; |
13 | 15 | use PHPStan\Reflection\ReflectionProvider; |
14 | 16 | use PHPStan\Rules\IdentifierRuleError; |
15 | 17 | use PHPStan\Rules\Rule; |
@@ -109,36 +111,29 @@ public function processNode(Node $callLike, Scope $scope): array |
109 | 111 | return []; |
110 | 112 | } |
111 | 113 |
|
112 | | - $args = $callLike->getArgs(); |
| 114 | + // Reorder arguments to account for named parameters |
| 115 | + $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs( |
| 116 | + $scope, |
| 117 | + $callLike->getArgs(), |
| 118 | + $methodReflection->getVariants(), |
| 119 | + $methodReflection->getNamedArgumentsVariants(), |
| 120 | + ); |
113 | 121 |
|
114 | | - if (\count($args) < 1) { |
115 | | - return []; |
116 | | - } |
| 122 | + $reorderedMethodCall = ArgumentsNormalizer::reorderMethodArguments( |
| 123 | + $parametersAcceptor, |
| 124 | + $callLike, |
| 125 | + ); |
117 | 126 |
|
118 | | - // Map function parameter names to parameter index |
119 | | - $params = $methodReflection->getVariants()[0]->getParameters(); |
120 | | - $paramNameToIndex = []; |
121 | | - foreach ($params as $i => $param) { |
122 | | - $paramNameToIndex[$param->getName()] = $i; |
| 127 | + if ($reorderedMethodCall === null) { |
| 128 | + return []; |
123 | 129 | } |
| 130 | + $reorderedArgs = $reorderedMethodCall->getArgs(); |
124 | 131 |
|
125 | | - // Map parameter positions to actual call arguments |
126 | | - $paramIndexToArg = []; |
127 | | - foreach ($args as $i => $arg) { |
128 | | - if ($arg->name === null) { |
129 | | - // Positional argument |
130 | | - $paramIndexToArg[$i] = $arg; |
131 | | - } else { |
132 | | - // Named argument (PHP 8.0+) |
133 | | - $name = $arg->name->toString(); |
134 | | - $index = $paramNameToIndex[$name] ?? null; |
135 | | - if ($index !== null) { |
136 | | - $paramIndexToArg[$index] = $arg; |
137 | | - } |
138 | | - } |
| 132 | + if (\count($reorderedArgs) < 1) { |
| 133 | + return []; |
139 | 134 | } |
140 | 135 |
|
141 | | - $tableExpr = $paramIndexToArg[0]->value; |
| 136 | + $tableExpr = $reorderedArgs[0]->value; |
142 | 137 | $tableType = $scope->getType($tableExpr); |
143 | 138 | $tableNames = $tableType->getConstantStrings(); |
144 | 139 | if (\count($tableNames) === 0) { |
@@ -166,11 +161,11 @@ public function processNode(Node $callLike, Scope $scope): array |
166 | 161 | foreach ($arrayArgPositions as $arrayArgPosition) { |
167 | 162 | // If the argument doesn't exist, just skip it since we don't want |
168 | 163 | // to error in case it has a default value |
169 | | - if (! \array_key_exists($arrayArgPosition, $paramIndexToArg)) { |
| 164 | + if (! \array_key_exists($arrayArgPosition, $reorderedArgs)) { |
170 | 165 | continue; |
171 | 166 | } |
172 | 167 |
|
173 | | - $argType = $scope->getType($paramIndexToArg[$arrayArgPosition]->value); |
| 168 | + $argType = $scope->getType($reorderedArgs[$arrayArgPosition]->value); |
174 | 169 | $argArrays = $argType->getConstantArrays(); |
175 | 170 | if (\count($argArrays) === 0) { |
176 | 171 | $errors[] = 'Argument #' . $arrayArgPosition . ' is not a constant array, got ' . $argType->describe(VerbosityLevel::precise()); |
|
0 commit comments