File Coverage

blib/lib/Perl/Critic/Policy/Freenode/PackageMatchesFilename.pm
Criterion Covered Total %
statement 40 41 97.5
branch 6 6 100.0
condition 4 8 50.0
subroutine 10 11 90.9
pod 4 4 100.0
total 64 70 91.4


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::Freenode::PackageMatchesFilename;
2              
3 1     1   644 use strict;
  1         3  
  1         28  
4 1     1   6 use warnings;
  1         2  
  1         29  
5              
6 1     1   5 use Perl::Critic::Utils qw(:severities :classification :ppi);
  1         2  
  1         52  
7 1     1   1191 use Path::Tiny 'path';
  1         11441  
  1         64  
8 1     1   9 use parent 'Perl::Critic::Policy';
  1         2  
  1         7  
9              
10             our $VERSION = '0.030';
11              
12 1     1   77 use constant DESC => 'No package matching the module filename';
  1         2  
  1         75  
13 1     1   8 use constant EXPL => 'A Perl module file is expected to contain a matching package name, so it can be used after loading it from the filesystem. A module file that doesn\'t contain a matching package name usually indicates an error.';
  1         1  
  1         376  
14              
15 1     1 1 18 sub default_severity { $SEVERITY_HIGH }
16 0     0 1 0 sub default_themes { 'freenode' }
17 4     4 1 32502 sub applies_to { 'PPI::Document' }
18              
19             sub violates {
20 4     4 1 45 my ($self, $elem, $doc) = @_;
21 4 100 33     14 return () unless $doc->is_module and $doc->filename and $doc->filename =~ m/\.pm\z/;
      66        
22            
23 3   50     101 my $packages = $elem->find('PPI::Statement::Package') || [];
24            
25 3         34 my $filepath = path($doc->filename)->realpath;
26 3         767 my $basename = $filepath->basename(qr/\.pm/);
27 3         118 $filepath = $filepath->parent->child($basename);
28            
29 3         184 my $found_match;
30 3         7 PKG: foreach my $package (@$packages) {
31 3         15 my $namespace = $package->namespace;
32 3         80 my $path_copy = $filepath;
33 3         11 foreach my $part (reverse split '::', $namespace) {
34 4 100       45 next PKG unless $part eq $path_copy->basename;
35 3         63 $path_copy = $path_copy->parent;
36             }
37 2         66 $found_match = 1;
38 2         5 last;
39             }
40            
41 3 100       33 return () if $found_match;
42 1         13 return $self->violation(DESC, EXPL, $elem);
43             }
44              
45             1;
46              
47             =head1 NAME
48              
49             Perl::Critic::Policy::Freenode::PackageMatchesFilename - Module files should
50             declare a package matching the filename
51              
52             =head1 DESCRIPTION
53              
54             Perl modules are normally loaded by C<require> (possibly via C<use> or C<no>).
55             When given a module name, C<require> will translate this into a filename and
56             then load whatever that file contains. The file doesn't need to actually
57             contain a package matching the module name initially given to C<require>, but
58             this can be confusing if later operations (including C<import> as called by
59             C<use>) expect the package to exist. Furthermore, the absence of such a package
60             is usually an indicator of a typo in the package name.
61              
62             ## in file My/Module.pm
63             package My::Module;
64              
65             This policy is similar to the core policy
66             L<Perl::Critic::Policy::Modules::RequireFilenameMatchesPackage>, but only
67             requires that one package name within a module file matches the filename.
68              
69             =head1 AFFILIATION
70              
71             This policy is part of L<Perl::Critic::Freenode>.
72              
73             =head1 CONFIGURATION
74              
75             This policy is not configurable except for the standard options.
76              
77             =head1 AUTHOR
78              
79             Dan Book, C<dbook@cpan.org>
80              
81             =head1 COPYRIGHT AND LICENSE
82              
83             Copyright 2015, Dan Book.
84              
85             This library is free software; you may redistribute it and/or modify it under
86             the terms of the Artistic License version 2.0.
87              
88             =head1 SEE ALSO
89              
90             L<Perl::Critic>