File Coverage

blib/lib/Perl/Lint/Policy/RegularExpressions/ProhibitEscapedMetacharacters.pm
Criterion Covered Total %
statement 42 42 100.0
branch 19 20 95.0
condition 6 6 100.0
subroutine 6 6 100.0
pod 0 1 0.0
total 73 75 97.3


line stmt bran cond sub pod time code
1             package Perl::Lint::Policy::RegularExpressions::ProhibitEscapedMetacharacters;
2 134     134   94215 use strict;
  134         266  
  134         4811  
3 134     134   600 use warnings;
  134         201  
  134         3563  
4 134     134   1149 use Perl::Lint::Constants::Type;
  134         202  
  134         85238  
5 134     134   795 use parent "Perl::Lint::Policy";
  134         252  
  134         818  
6              
7             use constant {
8 134         54485 DESC => 'Use character classes for literal metachars instead of escapes',
9             EXPL => [247],
10 134     134   9446 };
  134         263  
11              
12             sub evaluate {
13 10     10 0 30 my ($class, $file, $tokens, $src, $args) = @_;
14              
15 10         19 my @violations;
16 10         59 for (my $i = 0, my $token_type, my $is_reg_quote; my $token = $tokens->[$i]; $i++) {
17 347         386 $token_type = $token->{type};
18              
19 347 100 100     2185 if ($token_type == REG_EXP || $token_type == REG_REPLACE_FROM) {
    100 100        
20 50 100       180 if ($is_reg_quote) {
21 2         5 $is_reg_quote = 0;
22 2         7 next;
23             }
24              
25 48         84 my $regexp = $token->{data};
26              
27 48         47 my $maybe_regopt;
28 48 100       85 if ($token_type == REG_EXP) {
29 43         76 $maybe_regopt = $tokens->[$i+2];
30             }
31             else {
32 5         13 $maybe_regopt = $tokens->[$i+4];
33 5 100       30 if ($maybe_regopt->{type} == REG_DELIM) { # if it use brackets as delimiter
34 2         6 $maybe_regopt = $tokens->[$i+5];
35             }
36             }
37              
38 48         186 my $regex_to_detect = qr/[{}().*+?|# ]/;
39              
40 48 50       107 if ($maybe_regopt) {
41 48 100       118 if ($maybe_regopt->{type} == REG_OPT) {
42 40 100       141 if ($maybe_regopt->{data} =~ /x/) {
43 39         123 $regex_to_detect = qr/[{}().*+?| ]/;
44             }
45             }
46             }
47              
48 48 100       742 if (my @backslashes = $token->{data} =~ /(\\+)$regex_to_detect/g) {
49 22         74 for my $backslash (@backslashes) {
50 22 100       69 if (length($backslash) % 2 != 0) { # not escaped
51 21         133 push @violations, {
52             filename => $file,
53             line => $token->{line},
54             description => DESC,
55             explanation => EXPL,
56             policy => __PACKAGE__,
57             };
58 21         105 last;
59             }
60             }
61             }
62             }
63             elsif ($token_type == REG_QUOTE || $token_type == REG_DOUBLE_QUOTE) {
64 2         8 $is_reg_quote = 1;
65             }
66             }
67              
68 10         80 return \@violations;
69             }
70              
71             1;
72