Acme-Signature-Arity
view release on metacpan or search on metacpan
which mean something about the expected parameters.
Expected return information, as a list:
* number of required scalar parameters
* number of optional scalar parameters (probably because there are
defaults)
* a character representing the slurping behaviour, might be '@' or
'%', or nothing (undef?) if it's just a fixed list of scalar
parameters
This can also throw exceptions. That should only happen if you give it
something that isn't a coderef, or if internals change enough that the
entirely-unjustified assumptions made by this module are somehow no
longer valid. Maybe they never were in the first place.
max_arity
Takes a coderef, returns a number or undef.
If the code uses signatures, this tells you how many parameters you
could pass when calling before it complains - undef means unlimited.
Should also work when there are no signatures, just gives undef again.
min_arity
Takes a coderef, returns a number or undef.
If the code uses signatures, this tells you how many parameters you
need to pass when calling - 0 means that no parameters are required.
Should also work when there are no signatures, returning 0 in that
case.
coderef_ignoring_extra
Given a coderef, returns a coderef (either the original or wrapped)
lib/Acme/Signature/Arity.pm view on Meta::CPAN
which mean something about the expected parameters.
Expected return information, as a list:
=over 4
=item * number of required scalar parameters
=item * number of optional scalar parameters (probably because there are defaults)
=item * a character representing the slurping behaviour, might be '@' or '%', or nothing (undef?) if it's
just a fixed list of scalar parameters
=back
This can also throw exceptions. That should only happen if you give it something that isn't
a coderef, or if internals change enough that the entirely-unjustified assumptions made by
this module are somehow no longer valid. Maybe they never were in the first place.
=cut
lib/Acme/Signature/Arity.pm view on Meta::CPAN
my $cv = B::svref_2object($code);
die 'probably not a coderef' unless $cv->isa('B::CV');
my $next = $cv->START->next;
# we pretend sub { } is sub (@) { }, for convenience
return (0, 0, '@') unless $next and $next->isa('B::UNOP_AUX');
return $next->aux_list($cv);
}
=head2 max_arity
Takes a coderef, returns a number or C<undef>.
If the code uses signatures, this tells you how many parameters you could
pass when calling before it complains - C<undef> means unlimited.
Should also work when there are no signatures, just gives C<undef> again.
=cut
sub max_arity ($code) {
my ($scalars, $optional, $slurp) = arity($code);
return undef if $slurp;
return $scalars
}
=head2 min_arity
Takes a coderef, returns a number or C<undef>.
If the code uses signatures, this tells you how many parameters you need to
pass when calling - 0 means that no parameters are required.
Should also work when there are no signatures, returning 0 in that case.
=cut
sub min_arity ($code) {
my ($scalars, $optional, $slurp) = arity($code);
lib/Acme/Signature/Arity.pod view on Meta::CPAN
which mean something about the expected parameters.
Expected return information, as a list:
=over 4
=item * number of required scalar parameters
=item * number of optional scalar parameters (probably because there are defaults)
=item * a character representing the slurping behaviour, might be '@' or '%', or nothing (undef?) if it's
just a fixed list of scalar parameters
=back
This can also throw exceptions. That should only happen if you give it something that isn't
a coderef, or if internals change enough that the entirely-unjustified assumptions made by
this module are somehow no longer valid. Maybe they never were in the first place.
=head2 max_arity
Takes a coderef, returns a number or C<undef>.
If the code uses signatures, this tells you how many parameters you could
pass when calling before it complains - C<undef> means unlimited.
Should also work when there are no signatures, just gives C<undef> again.
=head2 min_arity
Takes a coderef, returns a number or C<undef>.
If the code uses signatures, this tells you how many parameters you need to
pass when calling - 0 means that no parameters are required.
Should also work when there are no signatures, returning 0 in that case.
=head2 coderef_ignoring_extra
Given a coderef, returns a coderef (either the original or wrapped)
which won't complain if you try to pass more parameters than it was expecting.
t/00-report-prereqs.t view on Meta::CPAN
# This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.028
use Test::More tests => 1;
use ExtUtils::MakeMaker;
use File::Spec;
# from $version::LAX
my $lax_version_re =
qr/(?: undef | (?: (?:[0-9]+) (?: \. | (?:\.[0-9]+) (?:_[0-9]+)? )?
|
(?:\.[0-9]+) (?:_[0-9]+)?
) | (?:
v (?:[0-9]+) (?: (?:\.[0-9]+)+ (?:_[0-9]+)? )?
|
(?:[0-9]+)? (?:\.[0-9]+){2,} (?:_[0-9]+)?
)
)/x;
# hide optional CPAN::Meta modules from prereq scanner
t/00-report-prereqs.t view on Meta::CPAN
for my $mod ( sort keys %{ $req_hash->{$phase}{$type} } ) {
next if $mod eq 'perl';
next if grep { $_ eq $mod } @exclude;
my $file = $mod;
$file =~ s{::}{/}g;
$file .= ".pm";
my ($prefix) = grep { -e File::Spec->catfile($_, $file) } @INC;
my $want = $req_hash->{$phase}{$type}{$mod};
$want = "undef" unless defined $want;
$want = "any" if !$want && $want == 0;
my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required";
if ($prefix) {
my $have = MM->parse_version( File::Spec->catfile($prefix, $file) );
$have = "undef" unless defined $have;
push @reports, [$mod, $want, $have];
if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) {
if ( $have !~ /\A$lax_version_re\z/ ) {
push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)";
}
elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) {
push @dep_errors, "$mod version '$have' is not in required range '$want'";
}
}
use warnings;
use Test::More;
use experimental qw(signatures);
use Acme::Signature::Arity;
for my $case (
[ 'sub () { }', min => 0, max => 0 ],
[ 'sub ($x) { }', min => 1, max => 1 ],
[ 'sub ($x, @) { }', min => 1, max => undef ],
[ 'sub ($x = 1, @) { }', min => 0, max => undef ],
[ 'sub ($x, $y = 1, @) { }', min => 1, max => undef ],
[ 'sub ($x, $y, %) { }', min => 2, max => undef ],
[ 'sub ($x, $y, $z = 5) { }', min => 2, max => 3 ],
[ 'sub { }', min => 0, max => undef ],
) {
my ($def, %args) = @$case;
subtest $def => sub {
my $code = eval $def;
is(min_arity($code), $args{min}, 'min arity is ' . ($args{min} // '<undef>')) or note explain [ arity($code) ] if exists $args{min};
is(max_arity($code), $args{max}, 'max arity is ' . ($args{max} // '<undef>')) or note explain [ arity($code) ] if exists $args{max};
done_testing;
};
}
is(eval {
Acme::Signature::Arity::coderef_ignoring_extra(sub ($x) {
die 'invalid data passed' unless $x eq "first"
})->("first", "second", 3, 4);
1
}, 1) or note explain $@;
( run in 2.106 seconds using v1.01-cache-2.11-cpan-d80b1682f3f )