Skip to content

Commit 2414522

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 f1a8d7d commit 2414522

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
@@ -4157,6 +4157,9 @@ which is forbidden. See L<perlvar/%{^HOOK}> and L<perlfunc/require EXPR>.
41574157
non-optional named parameter, but the caller did not provide a value associated
41584158
with that name. The caller of the subroutine is presumably at fault.
41594159

4160+
This message may report multiple parameter names, if more than one is found to
4161+
be missing. In that case it will use the word "parameters".
4162+
41604163
The message attempts to include the name of the called subroutine. If
41614164
the subroutine has been aliased, the subroutine's original name will be
41624165
shown, regardless of what name the caller used.
@@ -7525,6 +7528,9 @@ slurpy parameter, and the caller provided a name that did not
75257528
match any declared named parameter. The caller of the subroutine is
75267529
presumably at fault.
75277530

7531+
This message may report multiple parameter names, if more than one name was
7532+
passed that does not match. In that case it will use the word "parameters".
7533+
75287534
The message attempts to include the name of the called subroutine. If
75297535
the subroutine has been aliased, the subroutine's original name will be
75307536
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)