package Module::CPANTS::Kwalitee::FindModules; use warnings; use strict; use Data::Dumper; use File::Spec::Functions; sub order { 30 } ################################################################## # Analyse ################################################################## sub analyse { my $class=shift; my $me=shift; my $files=$me->d->{files_array}; if ($me->d->{meta_yml} && $me->d->{meta_yml}{provides}) { my $provides = $me->d->{meta_yml}{provides}; while (my ($module,$data)=each %$provides) { my $file=$data->{file}; my $found={ module=>$module, file=>$data->{file}, in_basedir=>0, in_lib=>0, }; my $loc; if ($file=~/^lib\W/) { $found->{in_lib}=1; } elsif ($file !~/\//) { $found->{in_basedir}=1; } push(@{$me->d->{modules}},$found); } } else { my %in_basedir= map {$_=>1} grep {/^[^\/]+\.pm$/} @$files; foreach my $file (@$files) { next unless $file=~/\.pm$/; next if $file=~m{^x?t/}; next if $file=~m{^test/}; next if $file=~m/^(bin|scripts?|ex|eg|examples?|samples?|demos?)\/\w/i; next if $file=~m{^inc/}; # skip Module::Install stuff # proper file in lib/ if ($file=~m|^lib/(.*)\.pm$|) { my $module=$1; $module=~s|/|::|g; push (@{$me->d->{modules}},{ module=>$module, file=>$file, in_basedir=>0, in_lib=>1, }); } else { # open file and find first package my $module; my $max_lines_to_look_at=666; open (my $fh,"<",catfile($me->distdir,$file)) || die "__PACKAGE__: Cannot open $file to find package declaration: $!"; while (my $line = <$fh>) { next if $line =~/^\s*#/; # ignore comments if ($line =~/^\s*package\s*(.*?)\s*;/) { $module=$1; last; } last if $line =~/^__(DATA|END)__/; $max_lines_to_look_at--; last unless $max_lines_to_look_at; } # try to guess from filename unless ($module) { $file=~m|(.*)\.pm$|; $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; } if ($module) { push(@{$me->d->{modules}}, { module=>$module, file=>$file, in_basedir=> $in_basedir{$file} ? 1 : 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 { $_->{in_basedir} } @$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 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