Acme-Signature-Arity

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

    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'";
                    }
                }

t/arity.t  view on Meta::CPAN

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 1.428 second using v1.01-cache-2.11-cpan-d80b1682f3f )