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   68620 use strict;
  133         191  
  133         3280  
3 133     133   425 use warnings;
  133         181  
  133         2477  
4 133     133   808 use Perl::Lint::Constants::Type;
  133         166  
  133         59307  
5 133     133   648 use parent "Perl::Lint::Policy";
  133         189  
  133         575  
6              
7             use constant {
8 133         57059 DESC => 'Private subroutine/method used',
9             EXPL => 'Use published APIs',
10 133     133   6873 };
  133         208  
11              
12             sub evaluate {
13 12     12 0 23 my ($class, $file, $tokens, $src, $args) = @_;
14              
15 12         18 my @allows = ();
16 12   100     68 for my $allow (split(/ /, $args->{protect_private_subs}->{allow} || '')) {
17 3         6 my @name_spaces = split /::/, $allow;
18 3         4 my $method_name = pop @name_spaces;
19 3         9 push @allows, +{
20             package_name => join('::', @name_spaces),
21             method_name => $method_name,
22             };
23             }
24 12   100     61 my $private_name_regex = $args->{protect_private_subs}->{private_name_regex} || '';
25              
26 12         12 my @violations;
27 12         15 my $module_name = '';
28 12         39 TOP: for (my $i = 0; my $token = $tokens->[$i]; $i++) {
29 380         275 my $token_type = $token->{type};
30 380         263 my $token_data = $token->{data};
31              
32 380 100 100     3717 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         37 my $delimiter = $token_data;
34              
35 54         53 $token = $tokens->[++$i];
36 54         41 $token_data = $token->{data};
37 54         51 my $next_token = $tokens->[$i+1];
38 54         36 my $next_token_type = $next_token->{type};
39 54 100 100     173 if (
      66        
40             substr($token_data, 0, 1) eq '_' &&
41             $next_token_type != POINTER &&
42             $next_token_type != NAMESPACE_RESOLVER
43             ) {
44 27         31 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         11 next TOP;
50             }
51             }
52              
53 22 100 100     99 if ($private_name_regex && $token_data =~ /$private_name_regex/) {
54 5         12 next;
55             }
56              
57             push @violations, {
58             filename => $file,
59             line => $token->{line},
60 17         54 description => DESC,
61             explanation => EXPL,
62             policy => __PACKAGE__,
63             };
64 17         32 $module_name = '';
65             }
66             else {
67 27         53 $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         13 $token_type = $token->{type};
77 18 100       30 if ($token_type == SEMI_COLON) {
78 3         6 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         80 $i++; # skip target func
88             }
89             elsif ($token_type == NAMESPACE) {
90 67         118 $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         9 $i++;
100 8         9 my $next_token = $tokens->[$i+1];
101 8 100 100     35 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         117 $module_name = '';
107             }
108             }
109              
110 12         46 return \@violations;
111             }
112              
113             1;
114