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   68322 use strict;
  133         201  
  133         3094  
3 133     133   420 use warnings;
  133         165  
  133         2359  
4 133     133   822 use Perl::Lint::Constants::Type;
  133         159  
  133         59699  
5 133     133   930 use Perl::Lint::Constants::Kind;
  133         187  
  133         6321  
6 133     133   492 use parent "Perl::Lint::Policy";
  133         167  
  133         577  
7              
8             use constant {
9 133         39198 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   6945 };
  133         179  
14              
15             sub evaluate {
16 4     4 0 10 my ($class, $file, $tokens, $src, $args) = @_;
17              
18 4         8 my $only_in_void_context = $args->{prohibit_backtick_operators}->{only_in_void_context};
19              
20 4         8 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         224 my $token_type = $token->{type};
26 304         176 my $token_kind = $token->{kind};
27              
28 304 100 66     720 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       320 if ($token_kind == KIND_STMT) {
34 17         15 $is_in_ctrl_context = 1;
35 17         26 next;
36             }
37              
38 279 100 100     566 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         8 my $left_paren_num = 1;
41 12         23 for ($i++; my $token = $tokens->[$i]; $i++) {
42 33         28 my $token_type = $token->{type};
43 33 50       72 if ($token_type == LEFT_PAREN) {
    100          
44 0         0 $left_paren_num++;
45             }
46             elsif ($token_type == RIGHT_PAREN) {
47 12 50       27 last if --$left_paren_num <= 0
48             }
49             }
50             }
51 17         13 $is_in_call_context = 0;
52 17         16 $is_in_ctrl_context = 0;
53 17         24 next;
54             }
55              
56 262 100       275 if ($token_type == ASSIGN) {
57 20         15 $is_in_assign_context = 1;
58 20         30 next;
59             }
60              
61 242 100       271 if ($token_type == SEMI_COLON) {
62 32         33 $is_in_assign_context = 0;
63 32         52 next;
64             }
65              
66 210 100 100     596 if ($token_type == EXEC_STRING || $token_type == REG_EXEC) {
67 39 100 100     95 next if ($only_in_void_context && $is_in_assign_context);
68              
69 29         25 my $desc = VOID_DESC;
70 29         20 my $expl = VOID_EXPL;
71 29 100       39 if ($is_in_assign_context) {
72 10         8 $desc = DESC;
73 10         7 $expl = EXPL;
74             }
75              
76             push @violations, {
77             filename => $file,
78             line => $token->{line},
79 29         124 description => $desc,
80             explanation => $expl,
81             policy => __PACKAGE__,
82             };
83             }
84             }
85              
86 4         19 return \@violations;
87             }
88              
89             1;
90