File Coverage

blib/lib/Perl/Lint/Policy/Subroutines/ProtectPrivateSubs.pm
Criterion Covered Total %
statement 54 54 100.0
branch 22 22 100.0
condition 44 52 84.6
subroutine 6 6 100.0
pod 0 1 0.0
total 126 135 93.3


line stmt bran cond sub pod time code
1             package Perl::Lint::Policy::Subroutines::ProtectPrivateSubs;
2 133     133   69432 use strict;
  133         204  
  133         3190  
3 133     133   459 use warnings;
  133         178  
  133         2508  
4 133     133   805 use Perl::Lint::Constants::Type;
  133         171  
  133         60239  
5 133     133   631 use parent "Perl::Lint::Policy";
  133         198  
  133         613  
6              
7             use constant {
8 133         57192 DESC => 'Private subroutine/method used',
9             EXPL => 'Use published APIs',
10 133     133   6535 };
  133         194  
11              
12             sub evaluate {
13 12     12 0 27 my ($class, $file, $tokens, $src, $args) = @_;
14              
15 12         23 my @allows = ();
16 12   100     71 for my $allow (split(/ /, $args->{protect_private_subs}->{allow} || '')) {
17 3         7 my @name_spaces = split /::/, $allow;
18 3         2 my $method_name = pop @name_spaces;
19 3         10 push @allows, +{
20             package_name => join('::', @name_spaces),
21             method_name => $method_name,
22             };
23             }
24 12   100     41 my $private_name_regex = $args->{protect_private_subs}->{private_name_regex} || '';
25              
26 12         8 my @violations;
27 12         18 my $module_name = '';
28 12         38 TOP: for (my $i = 0; my $token = $tokens->[$i]; $i++) {
29 380         236 my $token_type = $token->{type};
30 380         275 my $token_data = $token->{data};
31              
32 380 100 100     3730 if ($token_type == POINTER || $token_type == NAMESPACE_RESOLVER) {
    100 100        
    100 100        
    100 66        
    100 100        
    100 66        
      100        
      66        
      66        
      66        
      66        
33 54         38 my $delimiter = $token_data;
34              
35 54         48 $token = $tokens->[++$i];
36 54         41 $token_data = $token->{data};
37 54         42 my $next_token = $tokens->[$i+1];
38 54         46 my $next_token_type = $next_token->{type};
39 54 100 100     190 if (
      66        
40             substr($token_data, 0, 1) eq '_' &&
41             $next_token_type != POINTER &&
42             $next_token_type != NAMESPACE_RESOLVER
43             ) {
44 27         30 for my $allow (@allows) {
45 9 100 66     27 if (
46             $allow->{package_name} eq $module_name &&
47             $allow->{method_name} eq $token_data
48             ) {
49 5         10 next TOP;
50             }
51             }
52              
53 22 100 100     102 if ($private_name_regex && $token_data =~ /$private_name_regex/) {
54 5         9 next;
55             }
56              
57             push @violations, {
58             filename => $file,
59             line => $token->{line},
60 17         60 description => DESC,
61             explanation => EXPL,
62             policy => __PACKAGE__,
63             };
64 17         38 $module_name = '';
65             }
66             else {
67 27         51 $module_name .= $delimiter . $token_data;
68             }
69             }
70             elsif (
71             $token_type == USE_DECL ||
72             $token_type == REQUIRE_DECL ||
73             $token_type == PACKAGE
74             ) {
75 3         8 for ($i++; $token = $tokens->[$i]; $i++) {
76 18         14 $token_type = $token->{type};
77 18 100       29 if ($token_type == SEMI_COLON) {
78 3         7 last;
79             }
80             }
81             }
82             elsif (
83             ($token_type == SPECIFIC_KEYWORD && $token_data eq '__PACKAGE__') ||
84             ($token_type == BUILTIN_FUNC && $token_data eq 'shift') ||
85             ($token_type == NAMESPACE && $token_data eq 'POSIX')
86             ) {
87 43         61 $i++; # skip target func
88             }
89             elsif ($token_type == NAMESPACE) {
90 67         104 $module_name .= $token_data;
91             }
92             elsif (
93             (
94             $token_type == VAR ||
95             $token_type == GLOBAL_VAR ||
96             $token_type == LOCAL_VAR
97             ) && ($token_data eq '$pkg' || $token_data eq '$self')
98             ) {
99 8         8 $i++;
100 8         10 my $next_token = $tokens->[$i+1];
101 8 100 100     46 if ($next_token->{type} == NAMESPACE && $next_token->{data} eq 'SUPER') {
102 1         3 $i += 2;
103             }
104             }
105             elsif ($token_type == SEMI_COLON) {
106 74         118 $module_name = '';
107             }
108             }
109              
110 12         49 return \@violations;
111             }
112              
113             1;
114