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   89977 use strict;
  134         265  
  134         6147  
3 134     134   605 use warnings;
  134         209  
  134         3667  
4 134     134   982 use Perl::Lint::Constants::Type;
  134         200  
  134         83961  
5 134     134   834 use List::Util qw/any/;
  134         254  
  134         9028  
6 134     134   76872 use Email::Address;
  134         3217854  
  134         13305  
7 134     134   2058 use parent "Perl::Lint::Policy";
  134         317  
  134         1312  
8              
9             use constant {
10 134         82192 DESC => 'String *may* require interpolation',
11             EXPL => [51],
12 134     134   13053 };
  134         399  
13              
14             sub evaluate {
15 24     24 0 57 my ($class, $file, $tokens, $src, $args) = @_;
16              
17 24         44 my @rcs_keywords = ();
18 24 100       72 if (my $this_policies_arg = $args->{require_interpolation_of_matchers}) {
19 1   50     9 @rcs_keywords = split /\s+/, $this_policies_arg->{rcs_keywords} || '';
20             }
21              
22 24         31 my $is_used_vers = 0;
23              
24 24         28 my @violations;
25 24         74 for (my $i = 0, my $token_type, my $token_data; my $token = $tokens->[$i]; $i++) {
26 823         661 $token_type = $token->{type};
27 823         687 $token_data = $token->{data};
28              
29 823 100       1059 if ($token_type == USED_NAME) {
30 30 100       42 if ($token_data eq 'vars') {
31 10         7 $is_used_vers = 1;
32             }
33 30         52 next;
34             }
35              
36 793 100       967 if ($token_type == REG_QUOTE) {
37 33         31 $i++; # skip reg delimiter
38 33         34 $token = $tokens->[++$i];
39              
40 33         43 $token_data = $token->{data}; # It is REG_EXP, e.g. q{THIS ONE}
41 33         33 $token_type = RAW_STRING; # XXX
42             } # straight through!
43 793 100       1030 if ($token_type == RAW_STRING) {
44 152 100       215 if ($is_used_vers) {
45 13         22 next;
46             }
47              
48 139 100       729 if (my @captures = $token_data =~ /
49             (\\*)
50             (?:
51             [\$\@]([^\s{]\S*) |
52             \\[tnrfbae01234567xcNluLUEQ]
53             )/gx
54             ) {
55 74         77 my $length_of_captures = scalar @captures;
56 74         91 my $is_violated = 0;
57 74         124 for (my $i = 0; $i < $length_of_captures; $i++) {
58 154 100       208 if ($i % 2 == 0) {
59 77         75 my $backslash = $captures[$i];
60 77 100       132 if (length($backslash) % 2 == 0) { # check escaped or not
61 71         124 $is_violated = 1;
62             }
63             } else {
64 77 100 100     335 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         13 next;
72             }
73              
74 72   100     224 my ($var_name) = ($captures[$i] || '') =~ /\A(\w+)/;
75              
76 72 100   9   371 if (any {$_ eq $var_name} @rcs_keywords) {
  9         21  
77 8         6 $is_violated = 0;
78 8         25 next;
79             }
80              
81 64 100       164 if ($is_violated) {
82 58         220 push @violations, {
83             filename => $file,
84             line => $token->{line},
85             description => DESC,
86             explanation => EXPL,
87             policy => __PACKAGE__,
88             };
89 58         55 $is_violated = 0;
90 58         66 last;
91             }
92             }
93             }
94             }
95              
96 139         458 next;
97             }
98              
99 641 100       1250 if ($token_type == SEMI_COLON) {
100 147         121 $is_used_vers = 0;
101 147         235 next;
102             }
103             }
104              
105 24         121 return \@violations;
106             }
107              
108             1;
109