File Coverage

blib/lib/Perl/Lint/Policy/InputOutput/ProhibitBacktickOperators.pm
Criterion Covered Total %
statement 55 58 94.8
branch 22 24 91.6
condition 13 15 86.6
subroutine 7 7 100.0
pod 0 1 0.0
total 97 105 92.3


line stmt bran cond sub pod time code
1             package Perl::Lint::Policy::InputOutput::ProhibitBacktickOperators;
2 133     133   94070 use strict;
  133         269  
  133         4753  
3 133     133   590 use warnings;
  133         206  
  133         3372  
4 133     133   972 use Perl::Lint::Constants::Type;
  133         201  
  133         82910  
5 133     133   1326 use Perl::Lint::Constants::Kind;
  133         236  
  133         9124  
6 133     133   654 use parent "Perl::Lint::Policy";
  133         237  
  133         755  
7              
8             use constant {
9 133         53548 DESC => 'Backtick operator used',
10             EXPL => 'Use IPC::Open3 instead',
11             VOID_DESC => 'Backtick operator used in void context',
12             VOID_EXPL => 'Assign result to a variable or use system() instead',
13 133     133   9692 };
  133         246  
14              
15             sub evaluate {
16 4     4 0 11 my ($class, $file, $tokens, $src, $args) = @_;
17              
18 4         10 my $only_in_void_context = $args->{prohibit_backtick_operators}->{only_in_void_context};
19              
20 4         7 my @violations;
21             my $is_in_assign_context;
22 0         0 my $is_in_call_context;
23 0         0 my $is_in_ctrl_context;
24 4         19 for (my $i = 0; my $token = $tokens->[$i]; $i++) {
25 304         279 my $token_type = $token->{type};
26 304         236 my $token_kind = $token->{kind};
27              
28 304 100 66     803 if ($token_type == BUILTIN_FUNC || $token_type == KEY) {
29 8         10 $is_in_call_context = 1;
30 8         14 next;
31             }
32              
33 296 100       360 if ($token_kind == KIND_STMT) {
34 17         14 $is_in_ctrl_context = 1;
35 17         29 next;
36             }
37              
38 279 100 100     713 if ($only_in_void_context && ($is_in_call_context || $is_in_ctrl_context)) {
      66        
39 17 100       28 if ($token_type == LEFT_PAREN) {
40 12         9 my $left_paren_num = 1;
41 12         23 for ($i++; my $token = $tokens->[$i]; $i++) {
42 33         30 my $token_type = $token->{type};
43 33 50       77 if ($token_type == LEFT_PAREN) {
    100          
44 0         0 $left_paren_num++;
45             }
46             elsif ($token_type == RIGHT_PAREN) {
47 12 50       24 last if --$left_paren_num <= 0
48             }
49             }
50             }
51 17         13 $is_in_call_context = 0;
52 17         13 $is_in_ctrl_context = 0;
53 17         28 next;
54             }
55              
56 262 100       340 if ($token_type == ASSIGN) {
57 20         18 $is_in_assign_context = 1;
58 20         35 next;
59             }
60              
61 242 100       287 if ($token_type == SEMI_COLON) {
62 32         25 $is_in_assign_context = 0;
63 32         60 next;
64             }
65              
66 210 100 100     747 if ($token_type == EXEC_STRING || $token_type == REG_EXEC) {
67 39 100 100     110 next if ($only_in_void_context && $is_in_assign_context);
68              
69 29         24 my $desc = VOID_DESC;
70 29         23 my $expl = VOID_EXPL;
71 29 100       38 if ($is_in_assign_context) {
72 10         9 $desc = DESC;
73 10         8 $expl = EXPL;
74             }
75              
76 29         132 push @violations, {
77             filename => $file,
78             line => $token->{line},
79             description => $desc,
80             explanation => $expl,
81             policy => __PACKAGE__,
82             };
83             }
84             }
85              
86 4         23 return \@violations;
87             }
88              
89             1;
90