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 is used by other tests. =head3 analyse C first looks in C and F for C<*.pm> files. If it doesn't find any, it looks in the whole dist, but the C kwalitee point is only awarded if the modules are F or there's only one module in C. =head3 kwalitee_indicators Returns the Kwalitee Indicators datastructure. =over =item * proper_libs =back =head1 SEE ALSO L =head1 AUTHOR Thomas Klausner, , http://domm.zsi.at =head1 COPYRIGHT You may use and distribute this module according to the same terms that Perl is distributed under. =cut