File Coverage

blib/lib/Module/Checkstyle/Check/Subroutine.pm
Criterion Covered Total %
statement 58 59 98.3
branch 17 20 85.0
condition 7 12 58.3
subroutine 10 11 90.9
pod 4 4 100.0
total 96 106 90.5


line stmt bran cond sub pod time code
1             package Module::Checkstyle::Check::Subroutine;
2              
3 2     2   2026 use strict;
  2         5  
  2         78  
4 2     2   12 use warnings;
  2         4  
  2         73  
5              
6 2     2   12 use Carp qw(croak);
  2         3  
  2         156  
7 2     2   1039 use Readonly;
  2         3341  
  2         119  
8              
9 2     2   596 use Module::Checkstyle::Util qw(:args :problem);
  2         5  
  2         430  
10              
11 2     2   13 use base qw(Module::Checkstyle::Check);
  2         4  
  2         1599  
12              
13             # The directives we provide
14             Readonly my $MATCHES_NAME => 'matches-name';
15             Readonly my $MAX_LENGTH => 'max-length';
16             Readonly my $NO_FQN => 'no-fully-qualified-names';
17             Readonly my $NO_AMP_CALLS => 'no-calling-with-ampersand';
18              
19             sub register {
20             return (
21 0     0 1 0 'enter PPI::Statement::Sub' => \&handle_subroutine,
22             'PPI::Token::Symbol' => \&handle_symbol,
23             );
24             }
25              
26             sub new {
27 4     4 1 11 my ($class, $config) = @_;
28            
29 4         26 my $self = $class->SUPER::new($config);
30            
31             # Keep configuration local
32 4         14 $self->{$MATCHES_NAME} = as_regexp($config->get_directive($MATCHES_NAME));
33 4         32 $self->{$MAX_LENGTH} = as_numeric($config->get_directive($MAX_LENGTH));
34 4         32 $self->{$NO_FQN} = as_true($config->get_directive($NO_FQN));
35 4         30 $self->{$NO_AMP_CALLS} = as_true($config->get_directive($NO_AMP_CALLS));
36            
37 4         26 return $self;
38             }
39              
40             sub handle_subroutine {
41 8     8 1 20268 my ($self, $subroutine, $file) = @_;
42              
43 8         14 my @problems;
44              
45 8         23 push @problems, $self->_handle_naming($subroutine, $file);
46            
47             # Length
48 8 100       21 if ($self->{$MAX_LENGTH}) {
49 2         19 my $block = $subroutine->block();
50             # Forward declarations has no block hence no length to check
51 2 50       46 if (defined $block) {
52 2         13 my $first_line = $subroutine->location()->[0];
53 2         57 my $last_line = $block->last_element()->location()->[0];
54 2         38 my $length = $last_line - $first_line;
55 2 100       7 if ($length > $self->{$MAX_LENGTH}) {
56 1         13 my $name = $subroutine->name();
57 1         43 push @problems, new_problem($self->config, $MAX_LENGTH,
58             qq(Subroutine '$name' is too long ($length lines)),
59             $subroutine, $file);
60             }
61             }
62             }
63            
64 8         67 return @problems;
65             }
66              
67             sub _handle_naming {
68 8     8   11 my ($self, $subroutine, $file) = @_;
69              
70 8         10 my @problems;
71              
72             # Naming
73 8 100       39 if ($self->{$MATCHES_NAME}) {
74 3         30 my $name = $subroutine->name();
75 3 100 66     100 if ($name && $name !~ $self->{$MATCHES_NAME}) {
76 1         50 push @problems, new_problem($self->config, $MATCHES_NAME,
77             qq(Subroutine '$name' does not match '$self->{$MATCHES_NAME}'),
78             $subroutine, $file);
79             }
80             }
81              
82             # Qualified names
83 8 100       80 if ($self->{$NO_FQN}) {
84 3         23 my $name = $subroutine->name();
85 3 100 66     99 if ($name && $name =~ m{ :: | \' }x) {
86 2         8 push @problems, new_problem($self->config, $NO_FQN,
87             qq(Subroutine '$name' is fully qualified),
88             $subroutine, $file);
89             }
90             }
91            
92 8         41 return @problems;
93             }
94              
95             sub handle_symbol {
96 4     4 1 9996 my ($self, $symbol, $file) = @_;
97              
98             # We're only interested in what can be subroutine calls
99 4 50       17 return if $symbol->symbol_type() ne '&';
100              
101 4         92 my @problems;
102            
103 4 50       19 if ($self->{$NO_AMP_CALLS}) {
104 4         43 my $next_sibling = $symbol->snext_sibling();
105 4 100 33     160 if ($next_sibling && ref $next_sibling && $next_sibling->isa('PPI::Structure::List')) {
      66        
106 2         67 my $name = substr($symbol->content(), 1);
107 2         17 push @problems, new_problem($self->config, $NO_AMP_CALLS,
108             qq(Calling subroutine '$name' with ampersand),
109             $symbol, $file);
110             }
111             }
112              
113 4         19 return @problems;
114             }
115              
116             1;
117             __END__