Skip to content

Commit a965e73

Browse files
ruudkondrejmirtes
authored andcommitted
Use named argument in error for variadic types
When a type is variadic, and multiple named arguments are used, it's often hard to tell for which argument the error is coming. Since we have the named argument, we could use it in this situation.
1 parent d44f4df commit a965e73

File tree

10 files changed

+41
-27
lines changed

10 files changed

+41
-27
lines changed

src/Rules/AttributesCheck.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,14 @@ public function check(
144144
'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameters, at least %d required.',
145145
'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameter, %d-%d required.',
146146
'Attribute class ' . $attributeClassName . ' constructor invoked with %d parameters, %d-%d required.',
147-
'Parameter %s of attribute class ' . $attributeClassName . ' constructor expects %s, %s given.',
147+
'%s of attribute class ' . $attributeClassName . ' constructor expects %s, %s given.',
148148
'', // constructor does not have a return type
149-
'Parameter %s of attribute class ' . $attributeClassName . ' constructor is passed by reference, so it expects variables only',
149+
'%s of attribute class ' . $attributeClassName . ' constructor is passed by reference, so it expects variables only',
150150
'Unable to resolve the template type %s in instantiation of attribute class ' . $attributeClassName,
151151
'Missing parameter $%s in call to ' . $attributeClassName . ' constructor.',
152152
'Unknown parameter $%s in call to ' . $attributeClassName . ' constructor.',
153153
'Return type of call to ' . $attributeClassName . ' constructor contains unresolvable type.',
154-
'Parameter %s of attribute class ' . $attributeClassName . ' constructor contains unresolvable type.',
154+
'%s of attribute class ' . $attributeClassName . ' constructor contains unresolvable type.',
155155
'Attribute class ' . $attributeClassName . ' constructorinvoked with %s, but it\'s not allowed because of @no-named-arguments.',
156156
);
157157

src/Rules/Classes/InstantiationRule.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,14 +209,14 @@ private function checkClassName(string $class, bool $isName, Node $node, Scope $
209209
'Class ' . $classDisplayName . ' constructor invoked with %d parameters, at least %d required.',
210210
'Class ' . $classDisplayName . ' constructor invoked with %d parameter, %d-%d required.',
211211
'Class ' . $classDisplayName . ' constructor invoked with %d parameters, %d-%d required.',
212-
'Parameter %s of class ' . $classDisplayName . ' constructor expects %s, %s given.',
212+
'%s of class ' . $classDisplayName . ' constructor expects %s, %s given.',
213213
'', // constructor does not have a return type
214-
'Parameter %s of class ' . $classDisplayName . ' constructor is passed by reference, so it expects variables only',
214+
' %s of class ' . $classDisplayName . ' constructor is passed by reference, so it expects variables only',
215215
'Unable to resolve the template type %s in instantiation of class ' . $classDisplayName,
216216
'Missing parameter $%s in call to ' . $classDisplayName . ' constructor.',
217217
'Unknown parameter $%s in call to ' . $classDisplayName . ' constructor.',
218218
'Return type of call to ' . $classDisplayName . ' constructor contains unresolvable type.',
219-
'Parameter %s of class ' . $classDisplayName . ' constructor contains unresolvable type.',
219+
'%s of class ' . $classDisplayName . ' constructor contains unresolvable type.',
220220
'Class ' . $classDisplayName . ' constructor invoked with %s, but it\'s not allowed because of @no-named-arguments.',
221221
));
222222
}

src/Rules/FunctionCallParametersCheck.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
use function array_key_exists;
3131
use function count;
3232
use function implode;
33+
use function is_int;
3334
use function is_string;
3435
use function max;
3536
use function sprintf;
@@ -331,7 +332,7 @@ public function check(
331332
$verbosityLevel = VerbosityLevel::getRecommendedLevelByType($parameterType, $argumentValueType);
332333
$errors[] = RuleErrorBuilder::message(sprintf(
333334
$wrongArgumentTypeMessage,
334-
$this->describeParameter($parameter, $argumentName === null ? $i + 1 : null),
335+
$this->describeParameter($parameter, $argumentName ?? $i + 1),
335336
$parameterType->describe($verbosityLevel),
336337
$argumentValueType->describe($verbosityLevel),
337338
))
@@ -409,7 +410,7 @@ public function check(
409410
}
410411

411412
$errors[] = RuleErrorBuilder::message(sprintf(
412-
'Parameter %s is passed by reference so it does not accept %s.',
413+
'%s is passed by reference so it does not accept %s.',
413414
$this->describeParameter($parameter, $argumentName === null ? $i + 1 : null),
414415
$propertyDescription,
415416
))->identifier('argument.byRef')->line($argumentLine)->build();
@@ -625,11 +626,15 @@ private function processArguments(
625626
return [$errors, $newArguments];
626627
}
627628

628-
private function describeParameter(ParameterReflection $parameter, ?int $position): string
629+
private function describeParameter(ParameterReflection $parameter, int|string|null $positionOrNamed): string
629630
{
630631
$parts = [];
631-
if ($position !== null) {
632-
$parts[] = '#' . $position;
632+
if (is_int($positionOrNamed)) {
633+
$parts[] = 'Parameter #' . $positionOrNamed;
634+
} elseif ($parameter->isVariadic() && is_string($positionOrNamed)) {
635+
$parts[] = 'Named argument ' . $positionOrNamed . ' for variadic parameter';
636+
} else {
637+
$parts[] = 'Parameter';
633638
}
634639

635640
$name = $parameter->getName();

src/Rules/Functions/CallCallablesRule.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,14 @@ public function processNode(
126126
ucfirst($callableDescription) . ' invoked with %d parameters, at least %d required.',
127127
ucfirst($callableDescription) . ' invoked with %d parameter, %d-%d required.',
128128
ucfirst($callableDescription) . ' invoked with %d parameters, %d-%d required.',
129-
'Parameter %s of ' . $callableDescription . ' expects %s, %s given.',
129+
'%s of ' . $callableDescription . ' expects %s, %s given.',
130130
'Result of ' . $callableDescription . ' (void) is used.',
131-
'Parameter %s of ' . $callableDescription . ' is passed by reference, so it expects variables only.',
131+
'%s of ' . $callableDescription . ' is passed by reference, so it expects variables only.',
132132
'Unable to resolve the template type %s in call to ' . $callableDescription,
133133
'Missing parameter $%s in call to ' . $callableDescription . '.',
134134
'Unknown parameter $%s in call to ' . $callableDescription . '.',
135135
'Return type of call to ' . $callableDescription . ' contains unresolvable type.',
136-
'Parameter %s of ' . $callableDescription . ' contains unresolvable type.',
136+
'%s of ' . $callableDescription . ' contains unresolvable type.',
137137
ucfirst($callableDescription) . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.',
138138
),
139139
);

src/Rules/Functions/CallToFunctionParametersRule.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,14 @@ public function processNode(Node $node, Scope $scope): array
5757
'Function ' . $functionName . ' invoked with %d parameters, at least %d required.',
5858
'Function ' . $functionName . ' invoked with %d parameter, %d-%d required.',
5959
'Function ' . $functionName . ' invoked with %d parameters, %d-%d required.',
60-
'Parameter %s of function ' . $functionName . ' expects %s, %s given.',
60+
'%s of function ' . $functionName . ' expects %s, %s given.',
6161
'Result of function ' . $functionName . ' (void) is used.',
62-
'Parameter %s of function ' . $functionName . ' is passed by reference, so it expects variables only.',
62+
'%s of function ' . $functionName . ' is passed by reference, so it expects variables only.',
6363
'Unable to resolve the template type %s in call to function ' . $functionName,
6464
'Missing parameter $%s in call to function ' . $functionName . '.',
6565
'Unknown parameter $%s in call to function ' . $functionName . '.',
6666
'Return type of call to function ' . $functionName . ' contains unresolvable type.',
67-
'Parameter %s of function ' . $functionName . ' contains unresolvable type.',
67+
'%s of function ' . $functionName . ' contains unresolvable type.',
6868
'Function ' . $functionName . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.',
6969
);
7070
}

src/Rules/Functions/CallUserFuncRule.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,14 @@ public function processNode(Node $node, Scope $scope): array
7373
ucfirst($callableDescription) . ' invoked with %d parameters, at least %d required.',
7474
ucfirst($callableDescription) . ' invoked with %d parameter, %d-%d required.',
7575
ucfirst($callableDescription) . ' invoked with %d parameters, %d-%d required.',
76-
'Parameter %s of ' . $callableDescription . ' expects %s, %s given.',
76+
'%s of ' . $callableDescription . ' expects %s, %s given.',
7777
'Result of ' . $callableDescription . ' (void) is used.',
78-
'Parameter %s of ' . $callableDescription . ' is passed by reference, so it expects variables only.',
78+
'%s of ' . $callableDescription . ' is passed by reference, so it expects variables only.',
7979
'Unable to resolve the template type %s in call to ' . $callableDescription,
8080
'Missing parameter $%s in call to ' . $callableDescription . '.',
8181
'Unknown parameter $%s in call to ' . $callableDescription . '.',
8282
'Return type of call to ' . $callableDescription . ' contains unresolvable type.',
83-
'Parameter %s of ' . $callableDescription . ' contains unresolvable type.',
83+
'%s of ' . $callableDescription . ' contains unresolvable type.',
8484
ucfirst($callableDescription) . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.',
8585
);
8686
}

src/Rules/Methods/CallMethodsRule.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,14 @@ public function processNode(Node $node, Scope $scope): array
6363
'Method ' . $messagesMethodName . ' invoked with %d parameters, at least %d required.',
6464
'Method ' . $messagesMethodName . ' invoked with %d parameter, %d-%d required.',
6565
'Method ' . $messagesMethodName . ' invoked with %d parameters, %d-%d required.',
66-
'Parameter %s of method ' . $messagesMethodName . ' expects %s, %s given.',
66+
'%s of method ' . $messagesMethodName . ' expects %s, %s given.',
6767
'Result of method ' . $messagesMethodName . ' (void) is used.',
68-
'Parameter %s of method ' . $messagesMethodName . ' is passed by reference, so it expects variables only.',
68+
'%s of method ' . $messagesMethodName . ' is passed by reference, so it expects variables only.',
6969
'Unable to resolve the template type %s in call to method ' . $messagesMethodName,
7070
'Missing parameter $%s in call to method ' . $messagesMethodName . '.',
7171
'Unknown parameter $%s in call to method ' . $messagesMethodName . '.',
7272
'Return type of call to method ' . $messagesMethodName . ' contains unresolvable type.',
73-
'Parameter %s of method ' . $messagesMethodName . ' contains unresolvable type.',
73+
'%s of method ' . $messagesMethodName . ' contains unresolvable type.',
7474
'Method ' . $messagesMethodName . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.',
7575
));
7676
}

src/Rules/Methods/CallStaticMethodsRule.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,14 @@ public function processNode(Node $node, Scope $scope): array
7171
$displayMethodName . ' invoked with %d parameters, at least %d required.',
7272
$displayMethodName . ' invoked with %d parameter, %d-%d required.',
7373
$displayMethodName . ' invoked with %d parameters, %d-%d required.',
74-
'Parameter %s of ' . $lowercasedMethodName . ' expects %s, %s given.',
74+
'%s of ' . $lowercasedMethodName . ' expects %s, %s given.',
7575
'Result of ' . $lowercasedMethodName . ' (void) is used.',
76-
'Parameter %s of ' . $lowercasedMethodName . ' is passed by reference, so it expects variables only.',
76+
'%s of ' . $lowercasedMethodName . ' is passed by reference, so it expects variables only.',
7777
'Unable to resolve the template type %s in call to method ' . $lowercasedMethodName,
7878
'Missing parameter $%s in call to ' . $lowercasedMethodName . '.',
7979
'Unknown parameter $%s in call to ' . $lowercasedMethodName . '.',
8080
'Return type of call to ' . $lowercasedMethodName . ' contains unresolvable type.',
81-
'Parameter %s of ' . $lowercasedMethodName . ' contains unresolvable type.',
81+
'%s of ' . $lowercasedMethodName . ' contains unresolvable type.',
8282
$displayMethodName . ' invoked with %s, but it\'s not allowed because of @no-named-arguments.',
8383
));
8484

tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1907,7 +1907,7 @@ public function testNamedArguments(): void
19071907
91,
19081908
],
19091909
[
1910-
'Parameter ...$args of method NamedArgumentsMethod\Foo::doIpsum() expects string, int given.',
1910+
'Named argument foo for variadic parameter ...$args of method NamedArgumentsMethod\Foo::doIpsum() expects string, int given.',
19111911
91,
19121912
],
19131913
[
@@ -1922,6 +1922,14 @@ public function testNamedArguments(): void
19221922
'Unpacked argument (...) cannot be followed by a non-unpacked argument.',
19231923
94,
19241924
],
1925+
[
1926+
'Named argument foo for variadic parameter ...$args of method NamedArgumentsMethod\Foo::doIpsum() expects string, int given.',
1927+
95,
1928+
],
1929+
[
1930+
'Named argument bar for variadic parameter ...$args of method NamedArgumentsMethod\Foo::doIpsum() expects string, int given.',
1931+
95,
1932+
],
19251933
]);
19261934
}
19271935

tests/PHPStan/Rules/Methods/data/named-arguments.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ public function doDolor(): void
9292
$this->doIpsum(...['a' => 1, 'foo' => 'foo']);
9393
$this->doIpsum(...['b' => 1, 'foo' => 'foo']);
9494
$this->doIpsum(...[1, 2], 'foo');
95+
$this->doIpsum(1, 2, foo: 1, bar: 2);
9596
}
9697

9798
}

0 commit comments

Comments
 (0)