File Coverage

blib/lib/Module/CPANTS/Kwalitee/FindModules.pm
Criterion Covered Total %
statement 69 113 61.0
branch 32 68 47.0
condition 3 9 33.3
subroutine 8 10 80.0
pod 3 3 100.0
total 115 203 56.6


line stmt bran cond sub pod time code
1             package Module::CPANTS::Kwalitee::FindModules;
2 7     7   46070 use warnings;
  7         33  
  7         364  
3 7     7   56 use strict;
  7         14  
  7         267  
4 7     7   470 use File::Spec::Functions qw(catfile);
  7         804  
  7         11787  
5              
6             our $VERSION = '1.00';
7             $VERSION =~ s/_//; ## no critic
8              
9 49     49 1 162 sub order { 30 }
10              
11             ##################################################################
12             # Analyse
13             ##################################################################
14              
15             sub analyse {
16 11     11 1 35 my $class = shift;
17 11         30 my $me = shift;
18 11   50     251 my $files = $me->d->{files_array} || [];
19              
20 11 50 66     280 if ($me->d->{meta_yml} && $me->d->{meta_yml}{provides}) {
21 0         0 my $provides = $me->d->{meta_yml}{provides};
22 0         0 while (my ($module, $data) = each %$provides) {
23 0 0       0 next unless ref $data eq ref {}; # ignore wrong format
24 0   0     0 my $file = $data->{file} || '';
25 0         0 my $found = {
26             module => $module,
27             file => $file,
28             in_basedir => 0,
29             in_lib => 0,
30             };
31 0         0 my $loc;
32 0 0       0 if ($file =~ /^lib\W/) {
    0          
33 0         0 $found->{in_lib} = 1;
34             }
35             elsif ($file !~ /\//) {
36 0         0 $found->{in_basedir} = 1;
37             }
38              
39 0         0 push @{$me->d->{modules}}, $found;
  0         0  
40 0 0       0 if (exists $me->d->{files_hash}{$file}) {
41 0         0 $me->d->{files_hash}{$file}{module} = $module;
42             } else {
43 0         0 $found->{not_exists} = 1;
44             }
45             }
46             }
47             else {
48 11         177 my %in_basedir = map {$_ => 1} grep {/^[^\/]+\.pm$/} @$files;
  3         23  
  19         127  
49              
50 11         53 foreach my $file (@$files) {
51 19 100       93 next unless $file =~ /\.pm$/;
52 9 50       34 next if $file =~ m{^x?t/};
53 9 50       37 next if $file =~ m{^test/};
54 9 50       89 next if $file =~ m/^(bin|scripts?|ex|eg|examples?|samples?|demos?)\/\w/i;
55 9 50       40 next if $file =~ m{^inc/}; # skip Module::Install stuff
56 9 50       29 next if $file =~ m{^(local|perl5|fatlib)/};
57              
58             # proper file in lib/
59 9 100       68 if ($file =~ m|^lib/(.*)\.pm$|) {
60 6         22 my $module = $1;
61 6         48 $module =~ s|/|::|g;
62 6         16 push (@{$me->d->{modules}}, {
  6         128  
63             module => $module,
64             file => $file,
65             in_basedir => 0,
66             in_lib => 1,
67             });
68 6         185 $me->d->{files_hash}{$file}{module} = $module;
69             }
70             else {
71             # open file and find first package
72 3         7 my $module;
73 3         7 my $max_lines_to_look_at = 666;
74 3 50       89 open (my $fh, "<", catfile($me->distdir, $file)) or die "__PACKAGE__: Cannot open $file to find package declaration: $!";
75 3         201 while (my $line = <$fh>) {
76 3 50       16 next if $line =~ /^\s*#/; # ignore comments
77 3 50       38 if ($line =~ /^\s*package\s*(.*?)\s*;/) {
78 3         13 $module = $1;
79 3         8 last;
80             }
81 0 0       0 last if $line =~ /^__(DATA|END)__/;
82 0         0 $max_lines_to_look_at--;
83 0 0       0 last unless $max_lines_to_look_at;
84             }
85             # try to guess from filename
86 3 50       16 unless ($module) {
87 0         0 $file =~ m|(.*)\.pm$|;
88 0         0 $module = $1;
89 0         0 $module =~ s|^[a-z]+/||; # remove lowercase prefixes which most likely are not part of the distname (but something like 'src/')
90 0         0 $module =~ s|/|::|g;
91             }
92 3 50       10 if ($module) {
93 3         74 push(@{$me->d->{modules}}, {
94             module => $module,
95             file => $file,
96 3 50       19 in_basedir => $in_basedir{$file} ? 1 : 0,
97             in_lib => 0,
98             });
99 3         116 $me->d->{files_hash}{$file}{module} = $module;
100             }
101             }
102             }
103             }
104              
105 11         126 for my $file (keys %{$me->d->{files_hash}}) {
  11         211  
106 19 50       150 next unless $file =~ /^inc\/(.+)\.pm/;
107 0         0 my $module = $1;
108 0         0 $module =~ s|/|::|g;
109 0   0     0 push @{$me->d->{included_modules} ||= []}, $module;
  0         0  
110             }
111              
112 11 100       211 if (exists $me->d->{modules}) {
113 9         58 $me->d->{modules} = [sort {$a->{module} cmp $b->{module}} @{$me->d->{modules}}];
  0         0  
  9         167  
114             }
115 11 50       293 if (exists $me->d->{included_modules}) {
116 0         0 $me->d->{included_modules} = [sort @{$me->d->{included_modules}}];
  0         0  
117             }
118              
119 11         85 return 1;
120             }
121              
122              
123              
124             ##################################################################
125             # Kwalitee Indicators
126             ##################################################################
127              
128             sub kwalitee_indicators {
129             return [
130             {
131             name => 'proper_libs',
132             error => q{There is more than one .pm file in the base dir, or the .pm files are not in lib/ directory.},
133             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'. If you need to provide additional files, e.g. for testing, that should not be considered for Kwalitee, then you should look at the 'provides' map in META.yml to limit the files scanned; or use the 'no_index' map to exclude parts of the distribution.},
134             is_extra => 1,
135             code => sub {
136 11     11   256 my $d = shift;
137 11 100       27 my @modules = @{$d->{modules} || []};
  11         69  
138 11 100       40 return 1 unless @modules;
139              
140 9         27 my @not_in_lib = grep { !$_->{in_lib} } @modules;
  9         38  
141 9 100       49 return 1 unless @not_in_lib;
142              
143 3         9 my @in_basedir = grep { $_->{in_basedir} } @not_in_lib;
  3         12  
144 3 50       15 return 1 if @in_basedir == 1;
145              
146 0         0 $d->{error}{proper_libs} = join ', ', map {$_->{file}} @not_in_lib;
  0         0  
147              
148 0         0 return 0;
149             },
150             details => sub {
151 0     0   0 my $d = shift;
152 0 0       0 my @modules = @{$d->{modules} || []};
  0         0  
153 0 0       0 return "No modules were found" unless @modules;
154 0         0 return "The following files were found: ".$d->{error}{proper_libs};
155             },
156             },
157             {
158             name => 'no_missing_files_in_provides',
159             error => q{Provides field in the META.yml lists a file that does not found in the distribution.},
160             remedy => q{Use authoring tool like Dist::Zilla, Milla, and Minilla to generate correct provides.},
161             is_extra => 1,
162             code => sub {
163 11     11   74 my $d = shift;
164 11 100       26 my @modules = @{$d->{modules} || []};
  11         64  
165 11 100       65 return 1 unless @modules;
166              
167 9 50       29 if (my @not_exists = grep { $_->{not_exists} } @modules) {
  9         43  
168 0         0 $d->{error}{no_missing_files_in_provides} = join ', ', map {$_->{file}} @not_exists;
  0         0  
169 0         0 return 0;
170             }
171 9         27 return 1;
172             },
173             details => sub {
174 0     0   0 my $d = shift;
175 0 0       0 my @modules = @{$d->{modules} || []};
  0         0  
176 0 0       0 return "No modules were found" unless @modules;
177 0         0 return "The following files were missing: ".$d->{error}{no_missing_files_in_provides};
178             },
179             },
180 8     8 1 206 ];
181             }
182              
183              
184             q{Favourite record of the moment:
185             Fat Freddys Drop: Based on a true story};
186              
187              
188             __END__