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   68757 use strict;
  134         181  
  134         3099  
3 134     134   408 use warnings;
  134         156  
  134         2475  
4 134     134   775 use Perl::Lint::Constants::Type;
  134         153  
  134         61181  
5 134     134   573 use List::Util qw/any/;
  134         162  
  134         6833  
6 134     134   61343 use Email::Address;
  134         2331083  
  134         7327  
7 134     134   955 use parent "Perl::Lint::Policy";
  134         168  
  134         900  
8              
9             use constant {
10 134         58334 DESC => 'String *may* require interpolation',
11             EXPL => [51],
12 134     134   8738 };
  134         174  
13              
14             sub evaluate {
15 24     24 0 35 my ($class, $file, $tokens, $src, $args) = @_;
16              
17 24         35 my @rcs_keywords = ();
18 24 100       46 if (my $this_policies_arg = $args->{require_interpolation_of_matchers}) {
19 1   50     10 @rcs_keywords = split /\s+/, $this_policies_arg->{rcs_keywords} || '';
20             }
21              
22 24         23 my $is_used_vers = 0;
23              
24 24         20 my @violations;
25 24         62 for (my $i = 0, my $token_type, my $token_data; my $token = $tokens->[$i]; $i++) {
26 823         547 $token_type = $token->{type};
27 823         595 $token_data = $token->{data};
28              
29 823 100       898 if ($token_type == USED_NAME) {
30 30 100       40 if ($token_data eq 'vars') {
31 10         7 $is_used_vers = 1;
32             }
33 30         46 next;
34             }
35              
36 793 100       843 if ($token_type == REG_QUOTE) {
37 33         24 $i++; # skip reg delimiter
38 33         31 $token = $tokens->[++$i];
39              
40 33         43 $token_data = $token->{data}; # It is REG_EXP, e.g. q{THIS ONE}
41 33         26 $token_type = RAW_STRING; # XXX
42             } # straight through!
43 793 100       848 if ($token_type == RAW_STRING) {
44 152 100       180 if ($is_used_vers) {
45 13         17 next;
46             }
47              
48 139 100       548 if (my @captures = $token_data =~ /
49             (\\*)
50             (?:
51             [\$\@]([^\s{]\S*) |
52             \\[tnrfbae01234567xcNluLUEQ]
53             )/gx
54             ) {
55 74         54 my $length_of_captures = scalar @captures;
56 74         57 my $is_violated = 0;
57 74         107 for (my $i = 0; $i < $length_of_captures; $i++) {
58 154 100       171 if ($i % 2 == 0) {
59 77         70 my $backslash = $captures[$i];
60 77 100       97 if (length($backslash) % 2 == 0) { # check escaped or not
61 71         152 $is_violated = 1;
62             }
63             } else {
64 77 100 100     259 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     189 my ($var_name) = ($captures[$i] || '') =~ /\A(\w+)/;
75              
76 72 100   9   300 if (any {$_ eq $var_name} @rcs_keywords) {
  9         17  
77 8         8 $is_violated = 0;
78 8         23 next;
79             }
80              
81 64 100       133 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         46 $is_violated = 0;
90 58         55 last;
91             }
92             }
93             }
94             }
95              
96 139         281 next;
97             }
98              
99 641 100       1002 if ($token_type == SEMI_COLON) {
100 147         93 $is_used_vers = 0;
101 147         194 next;
102             }
103             }
104              
105 24         88 return \@violations;
106             }
107              
108             1;
109