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   69156 use strict;
  133         200  
  133         3259  
3 133     133   427 use warnings;
  133         170  
  133         2480  
4 133     133   772 use Perl::Lint::Constants::Type;
  133         155  
  133         61233  
5 133     133   912 use Perl::Lint::Constants::Kind;
  133         176  
  133         6559  
6 133     133   496 use parent "Perl::Lint::Policy";
  133         167  
  133         593  
7              
8             use constant {
9 133         40918 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   7393 };
  133         189  
14              
15             sub evaluate {
16 4     4 0 8 my ($class, $file, $tokens, $src, $args) = @_;
17              
18 4         9 my $only_in_void_context = $args->{prohibit_backtick_operators}->{only_in_void_context};
19              
20 4         5 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         18 for (my $i = 0; my $token = $tokens->[$i]; $i++) {
25 304         231 my $token_type = $token->{type};
26 304         172 my $token_kind = $token->{kind};
27              
28 304 100 66     729 if ($token_type == BUILTIN_FUNC || $token_type == KEY) {
29 8         8 $is_in_call_context = 1;
30 8         13 next;
31             }
32              
33 296 100       296 if ($token_kind == KIND_STMT) {
34 17         15 $is_in_ctrl_context = 1;
35 17         25 next;
36             }
37              
38 279 100 100     553 if ($only_in_void_context && ($is_in_call_context || $is_in_ctrl_context)) {
      66        
39 17 100       25 if ($token_type == LEFT_PAREN) {
40 12         10 my $left_paren_num = 1;
41 12         19 for ($i++; my $token = $tokens->[$i]; $i++) {
42 33         28 my $token_type = $token->{type};
43 33 50       79 if ($token_type == LEFT_PAREN) {
    100          
44 0         0 $left_paren_num++;
45             }
46             elsif ($token_type == RIGHT_PAREN) {
47 12 50       20 last if --$left_paren_num <= 0
48             }
49             }
50             }
51 17         13 $is_in_call_context = 0;
52 17         10 $is_in_ctrl_context = 0;
53 17         30 next;
54             }
55              
56 262 100       273 if ($token_type == ASSIGN) {
57 20         14 $is_in_assign_context = 1;
58 20         31 next;
59             }
60              
61 242 100       255 if ($token_type == SEMI_COLON) {
62 32         19 $is_in_assign_context = 0;
63 32         46 next;
64             }
65              
66 210 100 100     596 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         16 my $desc = VOID_DESC;
70 29         22 my $expl = VOID_EXPL;
71 29 100       32 if ($is_in_assign_context) {
72 10         9 $desc = DESC;
73 10         7 $expl = EXPL;
74             }
75              
76             push @violations, {
77             filename => $file,
78             line => $token->{line},
79 29         107 description => $desc,
80             explanation => $expl,
81             policy => __PACKAGE__,
82             };
83             }
84             }
85              
86 4         21 return \@violations;
87             }
88              
89             1;
90