File Coverage

blib/lib/Perl/Lint/Policy/ErrorHandling/RequireCarping.pm
Criterion Covered Total %
statement 78 81 96.3
branch 48 54 88.8
condition 70 80 87.5
subroutine 8 8 100.0
pod 0 1 0.0
total 204 224 91.0


line stmt bran cond sub pod time code
1             package Perl::Lint::Policy::ErrorHandling::RequireCarping;
2 133     133   70322 use strict;
  133         171  
  133         3102  
3 133     133   411 use warnings;
  133         157  
  133         2438  
4 133     133   821 use Perl::Lint::Constants::Type;
  133         159  
  133         57881  
5 133     133   547 use parent "Perl::Lint::Policy";
  133         145  
  133         615  
6              
7             use constant {
8 133         21443 DESC => q{Don't complain about die or warn if the message ends in a newline},
9             EXPL => [283],
10 133     133   6803 };
  133         166  
11              
12             sub evaluate {
13 29     29 0 49 my ($class, $file, $tokens, $src, $args) = @_;
14              
15 29         35 my $options = $args->{require_carping};
16 29         28 my $allow_messages_ending_with_newlines = 1;
17 29 100       58 if (defined $options->{allow_messages_ending_with_newlines}) {
18             $allow_messages_ending_with_newlines =
19 1         3 $options->{allow_messages_ending_with_newlines};
20             }
21             my $allow_in_main_unless_in_subroutine =
22 29   100     91 $options->{allow_in_main_unless_in_subroutine } || 0;
23              
24 29         24 my $is_in_main = 1;
25 29         23 my $is_in_sub = 0;
26              
27 29         28 my $left_brace_num = 0;
28              
29 29         26 my @violations;
30 29         27 my $token_num = scalar @$tokens;
31              
32 29         56 for (my $i = 0; $i < $token_num; $i++) {
33 357         269 my $token = $tokens->[$i];
34 357         254 my $token_type = $token->{type};
35 357         256 my $token_data = $token->{data};
36              
37 357 100 100     1213 if (
    100 66        
    100          
    100          
    100          
38             $token_type eq BUILTIN_FUNC &&
39             ($token_data eq 'die' || $token_data eq 'warn')
40             ) {
41 137         106 my %last_msg;
42 137         178 for ($i++; $i <= $token_num; $i++) {
  0         0  
43 789         596 $token = $tokens->[$i];
44 789         526 $token_type = $token->{type};
45 789         574 $token_data = $token->{data};
46              
47 133     133   520 no warnings qw/uninitialized/;
  133         168  
  133         47131  
48 789 100 100     10327 if ($token_type == STRING) {
    100 100        
    100 100        
    100 100        
    100 100        
    100 100        
    100 100        
    100 100        
    100 66        
    50 100        
      100        
      100        
      100        
      66        
49 82         172 %last_msg = (type => 'not_raw', data => $token_data);
50             }
51             elsif ($token_type == REG_DOUBLE_QUOTE) {
52 10         25 %last_msg = (type => 'not_raw', data => $tokens->[$i+=2]->{data});
53             }
54             elsif ($token_type == RAW_STRING) {
55 53         104 %last_msg = (type => 'raw', data => $token_data);
56             }
57             elsif ($token_type == REG_QUOTE) {
58 39         98 %last_msg = (type => 'raw', data => $tokens->[$i+=2]->{data});
59             }
60             elsif ($token_type == HERE_DOCUMENT_TAG || $token_type == HERE_DOCUMENT_RAW_TAG) {
61 2         6 %last_msg = (type => 'heredoc', data => $token_data);
62             }
63             elsif (
64             $i + 1 >= $token_num ||
65             $token_type == SEMI_COLON ||
66             $token_type == IF_STATEMENT ||
67             $token_type == UNLESS_STATEMENT ||
68             $token_type == WHILE_STATEMENT ||
69             $token_type == FOR_STATEMENT ||
70             $token_type == FOREACH_STATEMENT ||
71             $token_type == UNTIL_STATEMENT ||
72             $token_type == HERE_DOCUMENT_END
73             ) {
74 137         101 my $last_msg_type = $last_msg{type};
75 137         101 my $last_msg_data = $last_msg{data};
76              
77 137 100 66     970 if(
      66        
      66        
      66        
      100        
      100        
      66        
78             !(defined $last_msg_type && defined $last_msg_data) ||
79             ($last_msg_type eq 'raw' && (substr($last_msg_data, -1) ne "\n" || !$allow_messages_ending_with_newlines)) ||
80             ($last_msg_type eq 'not_raw' && ($last_msg_data !~ /(?:\\n|\n)\Z/ || !$allow_messages_ending_with_newlines))
81             ) {
82 82 100 66     353 if ($is_in_sub || !($is_in_main && $allow_in_main_unless_in_subroutine)) {
      100        
83             push @violations, {
84             filename => $file,
85             line => $token->{line} // $tokens->[-1]->{line},
86 74   66     267 description => DESC,
87             explanation => EXPL,
88             policy => __PACKAGE__,
89             };
90             }
91             }
92 137         296 last;
93             }
94             elsif ($token_type == METHOD) {
95 3         5 $i++; # Skip a left parenthesis
96 3         5 my $left_paren_num = 1;
97 3         7 for ($i++; $i < $token_num; $i++) {
98 7         5 my $token_type = $tokens->[$i]->{type};
99              
100 7 100       15 if ($token_type == RIGHT_PAREN) {
    50          
101 3         3 $left_paren_num--;
102             }
103             elsif ($token_type == LEFT_PAREN) {
104 0         0 $left_paren_num++;
105             }
106              
107 7 100       12 if ($left_paren_num <= 0) {
108 3         5 last;
109             }
110             }
111             }
112             elsif (
113             $token_type == BUILTIN_FUNC ||
114             $token_type == KEY
115             ) {
116 13         11 my $left_paren_num = 0;
117 13         25 for ($i++; $i < $token_num; $i++) {
118 21         20 my $token_type = $tokens->[$i]->{type};
119              
120 21 100       35 if ($token_type == RIGHT_PAREN) {
    100          
121 4         2 $left_paren_num--;
122             }
123             elsif ($token_type == LEFT_PAREN) {
124 4         4 $left_paren_num++;
125             }
126              
127 21 100       29 if ($left_paren_num <= 0) {
128 13         20 last;
129             }
130             }
131             }
132             elsif (
133             $token_type != REG_DELIM &&
134             $token_type != COMMA &&
135             $token_type != RIGHT_PAREN &&
136             $token_type != HERE_DOCUMENT &&
137             $token_type != RAW_HERE_DOCUMENT
138             ) {
139 207         308 %last_msg = ();
140             }
141             elsif ($token_type == PACKAGE) {
142 0 0       0 $is_in_main = $tokens->[++$i]->{data} eq 'main' ? 1 : 0;
143             }
144              
145 133     133   571 use warnings;
  133         171  
  133         20117  
146             }
147             }
148             elsif ($token_type == PACKAGE) {
149 2 50       10 $is_in_main = $tokens->[++$i]->{data} eq 'main' ? 1 : 0;
150             }
151             elsif ($token_type == FUNCTION_DECL) {
152 2         6 $is_in_sub = 1;
153             }
154             elsif ($token_type == LEFT_BRACE) {
155 5         8 $left_brace_num++;
156             }
157             elsif ($token_type == RIGHT_BRACE) {
158 9         7 $left_brace_num--;
159 9 50       15 if ($left_brace_num <= 0) {
160 9         13 $is_in_sub = 0;
161             }
162             }
163             }
164              
165 29         110 return \@violations;
166             }
167              
168             1;
169