File Coverage

blib/lib/Perl/Lint/Policy/InputOutput/RequireCheckedOpen.pm
Criterion Covered Total %
statement 95 109 87.1
branch 56 78 71.7
condition 22 48 45.8
subroutine 7 7 100.0
pod 0 1 0.0
total 180 243 74.0


line stmt bran cond sub pod time code
1             package Perl::Lint::Policy::InputOutput::RequireCheckedOpen;
2 133     133   71724 use strict;
  133         195  
  133         3208  
3 133     133   437 use warnings;
  133         169  
  133         2518  
4 133     133   827 use Perl::Lint::Constants::Type;
  133         164  
  133         59424  
5 133     133   958 use Perl::Lint::Constants::Kind;
  133         185  
  133         6541  
6 133     133   477 use parent "Perl::Lint::Policy";
  133         181  
  133         573  
7              
8             use constant {
9 133         87955 DESC => 'Return value of "open" ignored',
10             EXPL => 'Check the return value of "open" for success',
11 133     133   6491 };
  133         200  
12              
13             sub evaluate {
14 18     18 0 23 my ($class, $file, $tokens, $src, $args) = @_;
15              
16 18         16 my $is_in_assign_context = 0;
17 18         13 my $is_in_statement_context = 0;
18 18         12 my $is_called_open_in_void = 0;
19 18         14 my $is_enabled_autodie = 0;
20 18         14 my @violations;
21 18         40 for (my $i = 0; my $token = $tokens->[$i]; $i++) {
22 371         240 my $token_type = $token->{type};
23 371         223 my $token_kind = $token->{kind};
24 371         259 my $token_data = $token->{data};
25              
26 371 100       441 if ($token_type == ASSIGN) {
27 4         5 $is_in_assign_context = 1;
28 4         6 next;
29             }
30              
31 367 100       363 if ($token_type == USED_NAME) {
32 8 100       19 if ($token_data eq 'Fatal') {
    50          
33 4         5 my $next_token = $tokens->[$i+1];
34 4         5 my $next_token_type = $next_token->{type};
35 4 100 33     19 if ($next_token_type == REG_LIST) {
    100 33        
    50          
36 2         7 for ($i += 3; my $token = $tokens->[$i]; $i++) {
37 3         2 my $token_type = $token->{type};
38 3 100 100     17 if ($token_type == REG_EXP && $token->{data} eq 'open') {
    100          
39 1         5 return [];
40             }
41             elsif ($token_type == REG_DELIM) {
42 1         2 last;
43             }
44             }
45             }
46             elsif ($next_token_type == LEFT_PAREN) {
47 1         2 my $left_paren_num = 1;
48 1         5 for ($i += 2; my $token = $tokens->[$i]; $i++) {
49 1         2 my $token_type = $token->{type};
50 1 50 33     12 if ($token_type == LEFT_PAREN) {
    50 33        
51 0         0 $left_paren_num++;
52             }
53             elsif (($token_type == STRING || $token_type == RAW_STRING) && $token->{data} eq 'open') {
54 1         6 return [];
55             }
56             else {
57 0 0       0 last if --$left_paren_num <= 0;
58             }
59             }
60             }
61             elsif (($next_token_type == STRING || $next_token_type == RAW_STRING) && $next_token->{data} eq 'open') {
62 1         2 last;
63             }
64             }
65             elsif ($token_data eq 'autodie') {
66 4 100       10 if ($tokens->[$i+1]->{type} == REG_LIST) {
67 2         6 for ($i += 3; my $token = $tokens->[$i]; $i++) {
68 4         3 my $token_type = $token->{type};
69 4 100 100     28 if ($token_type == REG_EXP && $token->{data} =~ /\A\s*:io\s*\Z/) {
    100          
70 1         2 $is_enabled_autodie = 1;
71             }
72             elsif ($token_type == REG_DELIM) {
73 2         3 last;
74             }
75             }
76             }
77             else {
78 2         3 $is_enabled_autodie = 1;
79             }
80             }
81              
82 5         11 next;
83             }
84              
85 359 100 66     449 if ($token_type == NAMESPACE && $token_data eq 'Fatal') {
86 1         3 my $skipped_token = $tokens->[$i+2];
87 1 50 33     15 if ($skipped_token && $skipped_token->{type} == NAMESPACE && $skipped_token->{data} eq 'Exception') {
      33        
88 1         4 for ($i += 3; my $token = $tokens->[$i]; $i++) {
89 3         4 my $token_type = $token->{type};
90 3 100 66     20 if ($token_type == REG_LIST) {
    50 66        
    50          
    50          
91 1         3 for ($i += 2; my $token = $tokens->[$i]; $i++) {
92 1         2 my $token_type = $token->{type};
93 1 50 33     5 if ($token_type == REG_EXP && $token->{data} eq 'open') {
    0          
94 1         5 return [];
95             }
96             elsif ($token_type == REG_DELIM) {
97 0         0 last;
98             }
99             }
100             }
101             elsif ($token_type == LEFT_PAREN) {
102 0         0 my $left_paren_num = 1;
103 0         0 for ($i++; my $token = $tokens->[$i]; $i++) {
104 0         0 my $token_type = $token->{type};
105 0 0 0     0 if ($token_type == LEFT_PAREN) {
    0 0        
106 0         0 $left_paren_num++;
107             }
108             elsif (($token_type == STRING || $token_type == RAW_STRING) && $token->{data} eq 'open') {
109 0         0 return [];
110             }
111             else {
112 0 0       0 last if --$left_paren_num <= 0;
113             }
114             }
115             }
116             elsif (($token_type == STRING || $token_type == RAW_STRING) && $token->{data} eq 'open') {
117 0         0 last;
118             }
119             elsif ($token->{kind} == KIND_STMT_END) {
120 0         0 last;
121             }
122             }
123             }
124              
125 0         0 next;
126             }
127              
128 358 100       363 if ($token_kind == KIND_STMT) {
129 13         12 $is_in_statement_context = 1;
130              
131 13 100       21 if ($tokens->[$i+1]->{type} == LEFT_PAREN) {
132 1         2 $i++;
133 1         2 my $left_paren_num = 1;
134 1         4 for ($i++; my $token = $tokens->[$i]; $i++) {
135 1         1 my $token_type = $token->{type};
136 1 50       4 if ($token_type == LEFT_PAREN) {
137 0         0 $left_paren_num++;
138             }
139             else {
140 1 50       5 last if --$left_paren_num <= 0;
141             }
142             }
143             }
144 13         16 next;
145             }
146              
147 345 100       355 if ($token_type == BUILTIN_FUNC) {
148 47 100       61 if ($token_data eq 'open') {
    100          
149 36 100 66     77 if (!$is_in_assign_context && !$is_in_statement_context) {
150 20         13 $is_called_open_in_void = 1;
151             }
152             }
153             elsif ($token_data eq 'no') {
154 1         2 my $next_token = $tokens->[++$i];
155 1 50 33     7 if ($next_token->{type} == KEY && $next_token->{data} eq 'autodie') {
156 1         2 $is_enabled_autodie = 0;
157             }
158             }
159 47         72 next;
160             }
161              
162 298 100       305 if ($token_kind == KIND_OP) {
163 6         5 $is_called_open_in_void = 0;
164 6         8 next;
165             }
166              
167 292 100       496 if ($token_kind == KIND_STMT_END) {
168 44 100       53 next if $is_enabled_autodie;
169              
170 39 100       44 if ($is_called_open_in_void) {
171             push @violations, {
172             filename => $file,
173             line => $token->{line},
174 12         33 description => DESC,
175             explanation => EXPL,
176             policy => __PACKAGE__,
177             };
178             }
179              
180 39         27 $is_in_assign_context = 0;
181 39         24 $is_in_statement_context = 0;
182 39         27 $is_called_open_in_void = 0;
183 39         61 next;
184             }
185              
186             }
187              
188 15         44 return \@violations;
189             }
190              
191             1;
192