Skip to content

Commit dee8bc5

Browse files
committed
Collect names of multiple erroring parameters
Rather than stop immediately at the first failure, we can be a bit more helpful by collecting up potentially multiple names at once. We limit the list to 5 elements, just to limit the potential output in the case of accidentally passing a list of hundreds or thousands of elements into such a function.
1 parent 2371a9b commit dee8bc5

File tree

3 files changed

+64
-8
lines changed

3 files changed

+64
-8
lines changed

pod/perldiag.pod

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4167,6 +4167,9 @@ which is forbidden. See L<perlvar/%{^HOOK}> and L<perlfunc/require EXPR>.
41674167
non-optional named parameter, but the caller did not provide a value associated
41684168
with that name. The caller of the subroutine is presumably at fault.
41694169

4170+
This message may report multiple parameter names, if more than one is found to
4171+
be missing. In that case it will use the word "parameters".
4172+
41704173
The message attempts to include the name of the called subroutine. If
41714174
the subroutine has been aliased, the subroutine's original name will be
41724175
shown, regardless of what name the caller used.
@@ -7535,6 +7538,9 @@ slurpy parameter, and the caller provided a name that did not
75357538
match any declared named parameter. The caller of the subroutine is
75367539
presumably at fault.
75377540

7541+
This message may report multiple parameter names, if more than one name was
7542+
passed that does not match. In that case it will use the word "parameters".
7543+
75387544
The message attempts to include the name of the called subroutine. If
75397545
the subroutine has been aliased, the subroutine's original name will be
75407546
shown, regardless of what name the caller used.

pp.c

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7983,6 +7983,9 @@ PP(pp_multiparam)
79837983
SvPADSTALE_on(PAD_SVl(named->padix));
79847984
}
79857985

7986+
size_t n_errors = 0;
7987+
SV *error_names = NULL;
7988+
79867989
while(argc) {
79877990
SV **svp;
79887991

@@ -8060,22 +8063,48 @@ PP(pp_multiparam)
80608063
hv_store_ent(hv, name, newSVsv(val), 0);
80618064
}
80628065
else {
8063-
// TODO: Consider collecting up all the names of unrecognised
8064-
// in one string
8065-
croak_caller("Unrecognized named parameter '%" UTF8f "' to subroutine '%" SVf "'",
8066-
UTF8fARG(true, namelen, namepv), S_find_runcv_name());
8066+
n_errors++;
8067+
if(!error_names)
8068+
error_names = sv_2mortal(newSVpvs(""));
8069+
if(n_errors <= 5) {
8070+
/* Only bother collecting up the first 5 */
8071+
if(n_errors > 1)
8072+
sv_catpvs(error_names, ", ");
8073+
sv_catpvf(error_names, "'%" UTF8f "'", UTF8fARG(true, namelen, namepv));
8074+
}
80678075
}
80688076
}
80698077

8078+
if(n_errors) {
8079+
if(n_errors > 5)
8080+
sv_catpvs(error_names, ", ...");
8081+
/* diag_listed_as: Unrecognized named parameter '%s' to subroutine '%s' */
8082+
croak_caller("Unrecognized named parameter%s %" SVf " to subroutine '%" SVf "'",
8083+
n_errors > 1 ? "s" : "", SVfARG(error_names), SVfARG(S_find_runcv_name()));
8084+
}
8085+
80708086
for(size_t namedix = 0; namedix < n_named; namedix++) {
80718087
struct op_multiparam_named_aux *named = aux->named + namedix;
80728088
if(!named->is_required || !SvPADSTALE(PAD_SVl(named->padix)))
80738089
continue;
80748090

8075-
// TODO: Consider collecting up all the names of missing
8076-
// parameters in one string
8077-
croak_caller("Missing required named parameter '%" UTF8f "' to subroutine '%" SVf "'",
8078-
UTF8fARG(true, named->namelen, named->namepv), S_find_runcv_name());
8091+
n_errors++;
8092+
if(!error_names)
8093+
error_names = sv_2mortal(newSVpvs(""));
8094+
if(n_errors <= 5) {
8095+
/* Only bother collecting up the first 5 */
8096+
if(n_errors > 1)
8097+
sv_catpvs(error_names, ", ");
8098+
sv_catpvf(error_names, "'%" UTF8f "'", UTF8fARG(true, named->namelen, named->namepv));
8099+
}
8100+
}
8101+
8102+
if(n_errors) {
8103+
if(n_errors > 5)
8104+
sv_catpvs(error_names, ", ...");
8105+
/* diag_listed_as: Missing required named parameter '%s' to subroutine '%s' */
8106+
croak_caller("Missing required named parameter%s %" SVf " to subroutine '%" SVf "'",
8107+
n_errors > 1 ? "s" : "", SVfARG(error_names), SVfARG(S_find_runcv_name()));
80798108
}
80808109
}
80818110

t/lib/croak/signatures

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,9 +285,30 @@ f(alpha => 123); ## line 4
285285
EXPECT
286286
Missing required named parameter 'beta' to subroutine 'main::f' at - line 4.
287287
########
288+
# NAME multiple missing required named
289+
no warnings 'experimental::signature_named_parameters';
290+
sub f (:$alpha, :$beta) { } ## line 3
291+
f(); ## line 4
292+
EXPECT
293+
Missing required named parameters 'alpha', 'beta' to subroutine 'main::f' at - line 4.
294+
########
288295
# NAME unrecognised named
289296
no warnings 'experimental::signature_named_parameters';
290297
sub f (:$alpha) { } ## line 3
291298
f(alpha => 123, gamma => 456); ## line 4
292299
EXPECT
293300
Unrecognized named parameter 'gamma' to subroutine 'main::f' at - line 4.
301+
########
302+
# NAME multiple unrecognised named
303+
no warnings 'experimental::signature_named_parameters';
304+
sub f (:$alpha) { } ## line 3
305+
f(alpha => 123, gamma => 456, delta => 789); ## line 4
306+
EXPECT
307+
Unrecognized named parameters 'gamma', 'delta' to subroutine 'main::f' at - line 4.
308+
########
309+
# NAME multiple unrecognised named limiting
310+
no warnings 'experimental::signature_named_parameters';
311+
sub f (:$alpha) { } ## line 3
312+
f(alpha => 123, 'a' .. 'z'); ## line 4
313+
EXPECT
314+
Unrecognized named parameters 'a', 'c', 'e', 'g', 'i', ... to subroutine 'main::f' at - line 4.

0 commit comments

Comments
 (0)