The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
package Module::CPANTS::Kwalitee::Prereq;
use warnings;
use strict;
use File::Spec::Functions qw(catfile);

sub order { 100 }

##################################################################
# Analyse
##################################################################

sub analyse {
    my $class=shift;
    my $me=shift;
    
    my $files=$me->d->{files_array};
    my $distdir=$me->distdir;

    my $prereq;
    my $build;
    my $optional;
    my $yaml=$me->d->{meta_yml};
    if ($yaml) {
        if ($yaml->{requires}) {
            $prereq=$yaml->{requires};
        }
        if ($yaml->{build_requires}) {
            $build=$yaml->{build_requires};
        }
        if ($yaml->{recommends}) {
            $optional=$yaml->{recommends};
        }
        $me->d->{got_prereq_from}='META.yml';
    }
    elsif (grep {/^Build\.PL$/} @$files) {
        open(my $in, '<', catfile($distdir,'Build.PL')) || return 1;
        my $m=join '', <$in>;
        close $in;
        my($requires) = $m =~ /(?<!_)requires.*?=>.*?\{(.*?)\}/s;
        my($build_requires) = $m =~ /build_requires.*?=>.*?\{(.*?)\}/s;
        my($optional_requires) = $m =~ /recommends.*?=>.*?\{(.*?)\}/s;
        
        $me->d->{got_prereq_from}='Build.PL';

        ## no critic (ProhibitStringyEval)
        eval "{ no strict; \$prereq = { $requires \n} }";
        ## no critic (ProhibitStringyEval)
        eval "{ no strict; \$build = { $build_requires \n} }" if $build_requires;
        ## no critic (ProhibitStringyEval)
        eval "{ no strict; \$optional = { $optional_requires \n} }" if $optional_requires;
    }
    else {
        open(my $in, '<', catfile($distdir,'Makefile.PL')) || return 1;
        my $m=join '', <$in>;
        close $in;
        
        $me->d->{got_prereq_from}='Makefile.PL';

        my($requires) = $m =~ /PREREQ_PM.*?=>.*?\{(.*?)\}/s;
        $requires||='';
        ## no critic (ProhibitStringyEval)
        eval "{ no strict; \$prereq = { $requires \n} }";
    }
    return unless $prereq || $build || $optional;
    
    my %all=(
        prereq              => $prereq,
        build_prereq        => $build,
        optional_prereq     => $optional
    );

    my @clean;
    while (my ($type,$data)=each %all) {
        next unless $data;
        if (!ref $data) {
            my $p={$data=>0};
            $data=$p;
        }

        # sanitize version
        while (my($requires,$version)=each %$data) {
            $version||=0;
            $version=0 unless $version=~/[\d\._]+/;
            push(@clean,{
                requires=>$requires,
                version=>$version,
                'is_'.$type=>1,
            });
        }
    }
    $me->d->{prereq}=\@clean;
    return;
}

##################################################################
# Kwalitee Indicators
##################################################################

sub kwalitee_indicators{
    return [
        {
            name=>'is_prereq',
            error=>q{This distribution is not required by another distribution by another author.},
            remedy=>q{Convince / force / bribe another CPAN author to use this distribution.},
            code=>sub {
                # this metric can only be run from within 
                # Module::CPANTS::ProcessCPAN
                return 0;               
            },
            needs_db=>1,
            is_extra=>1,
        },
        {
            name=>'prereq_matches_use',
            error=>q{This distribution uses a module or a dist that's not listed as a prerequisite.},
            remedy=>q{List all used modules in META.yml requires},
            code=>sub {
                # this metric can only be run from within 
                # Module::CPANTS::ProcessCPAN
                return 0;               
            },
            needs_db=>1,
            is_extra=>1,
        },
        {
            name=>'build_prereq_matches_use',
            error=>q{This distribution uses a module or a dist in it's test suite that's not listed as a build prerequisite.},
            remedy=>q{List all modules used in the test suite in META.yml build_requires},
            code=>sub {
                # this metric can only be run from within 
                # Module::CPANTS::ProcessCPAN
                return 0;               
            },
            needs_db=>1,
            is_experimental=>1,
        },
        
    ];
}


q{Favourite record of the moment:
  Fat Freddys Drop: Based on a true story};

__END__

=pod

=head1 NAME

Module::CPANTS::Kwalitee::Prereq - Checks listed prerequistes

=head1 SYNOPSIS

Checks which other dists a dist declares as requirements.

=head1 DESCRIPTION

=head2 Methods

=head3 order

Defines the order in which Kwalitee tests should be run.

Returns C<100>.

=head3 analyse

C<MCK::Prereq> checks C<META.yml>, C<Build.PL> or C<Makefile.PL> for prereq-listings. 

=head3 kwalitee_indicators

Returns the Kwalitee Indicators datastructure.

=over

=item * is_prereq (currently deactived)

=back

=head1 SEE ALSO

L<Module::CPANTS::Analyse>

=head1 AUTHOR

Thomas Klausner, <domm@cpan.org>, http://domm.zsi.at

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2003-2006, 2009  Thomas Klausner

You may use and distribute this module according to the same terms
that Perl is distributed under.

=cut