File Coverage

blib/lib/Perl/Lint/Policy/ValuesAndExpressions/ProhibitQuotesAsQuotelikeOperatorDelimiters.pm
Criterion Covered Total %
statement 45 45 100.0
branch 15 16 93.7
condition 10 12 83.3
subroutine 6 6 100.0
pod 0 1 0.0
total 76 80 95.0


line stmt bran cond sub pod time code
1             package Perl::Lint::Policy::ValuesAndExpressions::ProhibitQuotesAsQuotelikeOperatorDelimiters;
2 133     133   70600 use strict;
  133         175  
  133         2981  
3 133     133   389 use warnings;
  133         141  
  133         2331  
4 133     133   739 use Perl::Lint::Constants::Type;
  133         146  
  133         62105  
5 133     133   565 use parent "Perl::Lint::Policy";
  133         155  
  133         592  
6              
7             use constant {
8 133         46857 EXPL => 'Using quotes as delimiters for quote-like operators obfuscates code',
9 133     133   6571 };
  133         160  
10              
11             my %TARGET_REGS = (
12             ®_QUOTE => 1,
13             ®_DOUBLE_QUOTE => 1,
14             ®_LIST => 1,
15             ®_EXEC => 1,
16             ®_DECL => 1,
17             ®_MATCH => 1,
18              
19             ®_ALL_REPLACE => 1,
20             );
21              
22             # TODO operator which has `replace from` and `replace to` doesn't work certainly.
23             # It maybe caused by Compiler::Lexer's bug.
24              
25             sub evaluate {
26 9     9 0 19 my ($class, $file, $tokens, $src, $args) = @_;
27              
28 9         39 my %target_regs_allows_single_quote = (
29             'qx' => 1,
30             'qr' => 1,
31             'm' => 1,
32             );
33 9 100       30 if (defined (my $single_quote_allowed_operators = $args->{single_quote_allowed_operators})) {
34 2         4 %target_regs_allows_single_quote = ();
35 2         18 for my $allow_delim (split qr/\s+/, $single_quote_allowed_operators) {
36 9         12 $target_regs_allows_single_quote{$allow_delim} = 1;
37             }
38             }
39              
40 9         16 my %target_regs_allows_double_quote = ();
41 9 100       24 if (defined (my $double_quote_allowed_operators = $args->{double_quote_allowed_operators})) {
42 2         18 for my $allow_delim (split qr/\s+/, $double_quote_allowed_operators) {
43 9         12 $target_regs_allows_double_quote{$allow_delim} = 1;
44             }
45             }
46              
47 9         19 my %target_regs_allows_back_quote = ();
48 9 100       21 if (defined (my $back_quote_allowed_operators = $args->{back_quote_allowed_operators})) {
49 2         19 for my $allow_delim (split qr/\s+/, $back_quote_allowed_operators) {
50 9         12 $target_regs_allows_back_quote{$allow_delim} = 1;
51             }
52             }
53              
54 9         16 my @violations;
55             my $next_token;
56 9         38 for (my $i = 0, my $token_type, my $token_data; my $token = $tokens->[$i]; $i++) {
57 474         315 $token_type = $token->{type};
58 474         321 $token_data = $token->{data};
59              
60 474 100       815 if ($TARGET_REGS{$token_type}) {
61 70         61 $next_token = $tokens->[++$i];
62 70 50 33     227 if ($next_token && $next_token->{type} == REG_DELIM) {
63 70         59 my $next_token_data= $next_token->{data};
64              
65 70         52 my $desc = '';
66 70 100 100     292 if ($next_token_data eq q<'> && !$target_regs_allows_single_quote{$token_data}) {
    100 100        
    100 100        
67 9         9 $desc= 'Single-quote used as quote-like operator delimiter';
68             }
69             elsif ($next_token_data eq q<"> && !$target_regs_allows_double_quote{$token_data}) {
70 17         15 $desc = 'Double-quote used as quote-like operator delimiter';
71             }
72             elsif ($next_token_data eq q<`> && !$target_regs_allows_back_quote{$token_data}) {
73 12         11 $desc = 'Back-quote (back-tick) used as quote-like operator delimiter';
74             }
75             else {
76 32         46 next;
77             }
78              
79             push @violations, {
80             filename => $file,
81             line => $next_token->{line},
82 38         132 description => $desc,
83             explanation => EXPL,
84             policy => __PACKAGE__,
85             };
86             }
87             }
88             }
89              
90 9         49 return \@violations;
91             }
92              
93             1;
94