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   70517 use strict;
  134         178  
  134         3287  
3 134     134   417 use warnings;
  134         155  
  134         2506  
4 134     134   770 use Perl::Lint::Constants::Type;
  134         155  
  134         61579  
5 134     134   575 use parent "Perl::Lint::Policy";
  134         155  
  134         589  
6              
7             use constant {
8 134         41143 DESC => 'Use character classes for literal metachars instead of escapes',
9             EXPL => [247],
10 134     134   6847 };
  134         180  
11              
12             sub evaluate {
13 10     10 0 16 my ($class, $file, $tokens, $src, $args) = @_;
14              
15 10         13 my @violations;
16 10         27 for (my $i = 0, my $token_type, my $is_reg_quote; my $token = $tokens->[$i]; $i++) {
17 347         231 $token_type = $token->{type};
18              
19 347 100 100     1499 if ($token_type == REG_EXP || $token_type == REG_REPLACE_FROM) {
    100 100        
20 50 100       64 if ($is_reg_quote) {
21 2         2 $is_reg_quote = 0;
22 2         4 next;
23             }
24              
25 48         42 my $regexp = $token->{data};
26              
27 48         24 my $maybe_regopt;
28 48 100       52 if ($token_type == REG_EXP) {
29 43         45 $maybe_regopt = $tokens->[$i+2];
30             }
31             else {
32 5         7 $maybe_regopt = $tokens->[$i+4];
33 5 100       11 if ($maybe_regopt->{type} == REG_DELIM) { # if it use brackets as delimiter
34 2         3 $maybe_regopt = $tokens->[$i+5];
35             }
36             }
37              
38 48         85 my $regex_to_detect = qr/[{}().*+?|# ]/;
39              
40 48 50       64 if ($maybe_regopt) {
41 48 100       68 if ($maybe_regopt->{type} == REG_OPT) {
42 40 100       64 if ($maybe_regopt->{data} =~ /x/) {
43 39         54 $regex_to_detect = qr/[{}().*+?| ]/;
44             }
45             }
46             }
47              
48 48 100       342 if (my @backslashes = $token->{data} =~ /(\\+)$regex_to_detect/g) {
49 22         21 for my $backslash (@backslashes) {
50 22 100       34 if (length($backslash) % 2 != 0) { # not escaped
51             push @violations, {
52             filename => $file,
53             line => $token->{line},
54 21         58 description => DESC,
55             explanation => EXPL,
56             policy => __PACKAGE__,
57             };
58 21         59 last;
59             }
60             }
61             }
62             }
63             elsif ($token_type == REG_QUOTE || $token_type == REG_DOUBLE_QUOTE) {
64 2         4 $is_reg_quote = 1;
65             }
66             }
67              
68 10         36 return \@violations;
69             }
70              
71             1;
72