File Coverage

blib/lib/Perl/Lint/Policy/ValuesAndExpressions/RequireInterpolationOfMetachars.pm
Criterion Covered Total %
statement 66 66 100.0
branch 26 26 100.0
condition 12 13 92.3
subroutine 9 9 100.0
pod 0 1 0.0
total 113 115 98.2


line stmt bran cond sub pod time code
1             package Perl::Lint::Policy::ValuesAndExpressions::RequireInterpolationOfMetachars;
2 134     134   70296 use strict;
  134         186  
  134         3020  
3 134     134   415 use warnings;
  134         191  
  134         2422  
4 134     134   792 use Perl::Lint::Constants::Type;
  134         161  
  134         60560  
5 134     134   606 use List::Util qw/any/;
  134         160  
  134         6821  
6 134     134   61043 use Email::Address;
  134         2305388  
  134         6957  
7 134     134   914 use parent "Perl::Lint::Policy";
  134         168  
  134         898  
8              
9             use constant {
10 134         58741 DESC => 'String *may* require interpolation',
11             EXPL => [51],
12 134     134   8517 };
  134         171  
13              
14             sub evaluate {
15 24     24 0 46 my ($class, $file, $tokens, $src, $args) = @_;
16              
17 24         27 my @rcs_keywords = ();
18 24 100       54 if (my $this_policies_arg = $args->{require_interpolation_of_matchers}) {
19 1   50     7 @rcs_keywords = split /\s+/, $this_policies_arg->{rcs_keywords} || '';
20             }
21              
22 24         23 my $is_used_vers = 0;
23              
24 24         22 my @violations;
25 24         67 for (my $i = 0, my $token_type, my $token_data; my $token = $tokens->[$i]; $i++) {
26 823         573 $token_type = $token->{type};
27 823         575 $token_data = $token->{data};
28              
29 823 100       869 if ($token_type == USED_NAME) {
30 30 100       45 if ($token_data eq 'vars') {
31 10         8 $is_used_vers = 1;
32             }
33 30         39 next;
34             }
35              
36 793 100       812 if ($token_type == REG_QUOTE) {
37 33         27 $i++; # skip reg delimiter
38 33         33 $token = $tokens->[++$i];
39              
40 33         31 $token_data = $token->{data}; # It is REG_EXP, e.g. q{THIS ONE}
41 33         23 $token_type = RAW_STRING; # XXX
42             } # straight through!
43 793 100       891 if ($token_type == RAW_STRING) {
44 152 100       176 if ($is_used_vers) {
45 13         16 next;
46             }
47              
48 139 100       521 if (my @captures = $token_data =~ /
49             (\\*)
50             (?:
51             [\$\@]([^\s{]\S*) |
52             \\[tnrfbae01234567xcNluLUEQ]
53             )/gx
54             ) {
55 74         63 my $length_of_captures = scalar @captures;
56 74         54 my $is_violated = 0;
57 74         100 for (my $i = 0; $i < $length_of_captures; $i++) {
58 154 100       177 if ($i % 2 == 0) {
59 77         67 my $backslash = $captures[$i];
60 77 100       103 if (length($backslash) % 2 == 0) { # check escaped or not
61 71         109 $is_violated = 1;
62             }
63             } else {
64 77 100 100     255 if (
      100        
      100        
65             # ports from Perl::Critic::Policy::ValuesAndExpressions::RequireInterpolationOfMetachars
66             index ($token_data, q<@>) >= 0 &&
67             $token_data !~ m< \W \@ >xms &&
68             $token_data !~ m< \A \@ \w+ \b >xms &&
69             $token_data =~ $Email::Address::addr_spec
70             ) {
71 5         9 next;
72             }
73              
74 72   100     186 my ($var_name) = ($captures[$i] || '') =~ /\A(\w+)/;
75              
76 72 100   9   291 if (any {$_ eq $var_name} @rcs_keywords) {
  9         14  
77 8         7 $is_violated = 0;
78 8         22 next;
79             }
80              
81 64 100       131 if ($is_violated) {
82             push @violations, {
83             filename => $file,
84             line => $token->{line},
85 58         164 description => DESC,
86             explanation => EXPL,
87             policy => __PACKAGE__,
88             };
89 58         44 $is_violated = 0;
90 58         61 last;
91             }
92             }
93             }
94             }
95              
96 139         246 next;
97             }
98              
99 641 100       1031 if ($token_type == SEMI_COLON) {
100 147         110 $is_used_vers = 0;
101 147         203 next;
102             }
103             }
104              
105 24         86 return \@violations;
106             }
107              
108             1;
109