package Module::CPANTS::Kwalitee::FindModules;
use warnings;
use strict;
use Data::Dumper;
sub order { 30 }
##################################################################
# Analyse
##################################################################
sub analyse {
my $class=shift;
my $me=shift;
my $files=$me->d->{files_array};
# use provides (META.yml) if available
my $meta=$me->d->{meta_yml};
if (my $provides=$meta->{provides}) {
while (my ($module,$data)=each %$provides) {
my $where='unknown';
if ($data->{file} =~ m|lib/|) {
$where='lib';
}
elsif ($data->{file} !~ m|/|) {
$where='base';
}
push(@{$me->d->{modules}},
{
module=>$module,
file=>$data->{file},
in_basedir=>$where eq 'base' ? 1 : 0,
in_lib=> $where eq 'lib' ? 1 : 0,
});
}
return;
}
my @modules_basedir=grep {/^[^\/]+\.pm$/} @$files;
if (@modules_basedir) {
my $namespace=$me->d->{dist} || die 'unknown namespace '.Dumper($me);
# try to guess the namespace
if ($namespace=~/-/) {
# multi-level namespace
$namespace=~s/-[^-]+$/-/; # remove last part of name
$namespace=~s/-/::/g;
}
# single level namespace (e.g. 'threads')
else {
$namespace='';
}
foreach my $file (@modules_basedir) {
my $module=$namespace.$file;
$module=~s/\.pm$//;
push(@{$me->d->{modules}},
{
module=>$module,
file=>$file,
in_basedir=>1,
in_lib=>0,
});
}
}
if ($me->d->{dir_lib} == 1) {
my @modules_path;
foreach my $file (@$files) {
next unless $file=~m|^lib/(.*)\.pm$|;
my $module=$1;
$module=~s|/|::|g;
push (@{$me->d->{modules}},
{
module=>$module,
file=>$file,
in_basedir=>0,
in_lib=>1,
});
}
}
if (!@modules_basedir && !$me->d->{dir_lib}) {
my @modules_path;
foreach my $file (@$files) {
next unless $file=~/\.pm$/;
next if $file=~m{/t/};
next if $file=~m{/test/};
next if $file=~m{/inc/}; # skip Module::Install stuff
$file=~m|(.*)\.pm$|;
my $module=$1;
$module=~s|^[a-z]+/||; # remove lowercase prefixes which most likely are not part of the distname (but something like 'src/')
$module=~s|/|::|g;
push(@{$me->d->{modules}},
{
module=>$module,
file=>$file,
in_basedir=>0,
in_lib=>0,
});
}
}
return 1;
}
##################################################################
# Kwalitee Indicators
##################################################################
sub kwalitee_indicators {
return [
{
name=>'proper_libs',
error=>q{There is more than one .pm file in the base dir, or the .pm files are not in directory lib.},
remedy=>q{Move your *.pm files in a directory named 'lib'. The directory structure should look like 'lib/Your/Module.pm' for a module named 'Your::Module'.},
code=>sub {
my $d=shift;
my $modules=$d->{modules};
return 0 unless $modules;
my @in_basedir=grep { $_->{file} !~ m|/| } @$modules;
return 1 if $d->{dir_lib} && @in_basedir == 0;
return 1 if @in_basedir == 1;
return 0;
},
},
];
}
q{Favourite record of the moment:
Fat Freddys Drop: Based on a true story};
__END__
=pod
=head1 NAME
Module::CPANTS::Kwalitee::FindModules - Find modules provided by a dist
=head1 SYNOPSIS
Finds and reports all modules (i.e. F<*.pm> files) in a distribution.
=head1 DESCRIPTION
=head2 Methods
=head3 order
Defines the order in which Kwalitee tests should be run.
Returns C<30>, as data generated by C<MCK::FindModules> is used by other tests.
=head3 analyse
C<MCK::FindModules> first looks in C<basedir> and F<lib/> for C<*.pm> files. If it doesn't find any, it looks in the whole dist, but the C<proper_libs> kwalitee point is only awarded if the modules are F<lib/> or there's only one module in C<basedir>.
=head3 kwalitee_indicators
Returns the Kwalitee Indicators datastructure.
=over
=item * proper_libs
=back
=head1 SEE ALSO
L<Module::CPANTS::Analyse>
=head1 AUTHOR
Thomas Klausner, <domm@cpan.org>, http://domm.zsi.at
=head1 COPYRIGHT
You may use and distribute this module according to the same terms
that Perl is distributed under.
=cut
syntax highlighted by Code2HTML, v. 0.9.1