File Coverage

blib/lib/Perl/Critic/Policy/RegularExpressions/ProhibitSingleCharAlternation.pm
Criterion Covered Total %
statement 21 42 50.0
branch 0 18 0.0
condition 0 12 0.0
subroutine 10 12 83.3
pod 4 5 80.0
total 35 89 39.3


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::RegularExpressions::ProhibitSingleCharAlternation;
2              
3 40     40   26330 use 5.010001;
  40         195  
4 40     40   268 use strict;
  40         156  
  40         909  
5 40     40   258 use warnings;
  40         158  
  40         1122  
6              
7 40     40   292 use Readonly;
  40         152  
  40         2258  
8              
9 40     40   322 use Perl::Critic::Utils qw( :characters :severities );
  40         124  
  40         2171  
10 40     40   12048 use parent 'Perl::Critic::Policy';
  40         142  
  40         362  
11              
12             our $VERSION = '1.150';
13              
14             #-----------------------------------------------------------------------------
15              
16             Readonly::Scalar my $EXPL => [265];
17              
18             #-----------------------------------------------------------------------------
19              
20 89     89 0 1598 sub supported_parameters { return qw() }
21 74     74 1 368 sub default_severity { return $SEVERITY_LOWEST }
22 86     86 1 358 sub default_themes { return qw( core pbp performance ) }
23 30     30 1 101 sub applies_to { return qw(PPI::Token::Regexp::Match
24             PPI::Token::Regexp::Substitute
25             PPI::Token::QuoteLike::Regexp) }
26              
27             #-----------------------------------------------------------------------------
28              
29             sub violates {
30 0     0 1   my ( $self, $elem, $document ) = @_;
31              
32             # optimization: don't bother parsing the regexp if there are no pipes
33 0 0         return if $elem !~ m/[|]/xms;
34              
35 0 0         my $re = $document->ppix_regexp_from_element( $elem ) or return;
36 0 0         $re->failures() and return;
37              
38 0           my @violations;
39 0           foreach my $node ( @{ $re->find_parents( sub {
40 0   0 0     return $_[1]->isa( 'PPIx::Regexp::Token::Operator' )
41             && $_[1]->content() eq q<|>;
42 0 0         } ) || [] } ) {
43              
44 0           my @singles;
45             my @alternative;
46 0           foreach my $kid ( $node->children() ) {
47 0 0 0       if ( $kid->isa( 'PPIx::Regexp::Token::Operator' )
    0          
48             && $kid->content() eq q<|>
49             ) {
50             @alternative == 1
51             and $alternative[0]->isa( 'PPIx::Regexp::Token::Literal' )
52 0 0 0       and push @singles, map { $_->content() } @alternative;
  0            
53 0           @alternative = ();
54             } elsif ( $kid->significant() ) {
55 0           push @alternative, $kid;
56             }
57             }
58             @alternative == 1
59             and $alternative[0]->isa( 'PPIx::Regexp::Token::Literal' )
60 0 0 0       and push @singles, map { $_->content() } @alternative;
  0            
61              
62 0 0         if ( 1 < @singles ) {
63 0           my $description =
64             'Use ['
65             . join( $EMPTY, @singles )
66             . '] instead of '
67             . join q<|>, @singles;
68 0           push @violations, $self->violation( $description, $EXPL, $elem );
69             }
70             }
71              
72 0           return @violations;
73             }
74              
75             1;
76              
77             __END__
78              
79             #-----------------------------------------------------------------------------
80              
81             =pod
82              
83             =head1 NAME
84              
85             Perl::Critic::Policy::RegularExpressions::ProhibitSingleCharAlternation - Use C<[abc]> instead of C<a|b|c>.
86              
87              
88             =head1 AFFILIATION
89              
90             This Policy is part of the core L<Perl::Critic|Perl::Critic>
91             distribution.
92              
93              
94             =head1 DESCRIPTION
95              
96             Character classes (like C<[abc]>) are significantly faster than single
97             character alternations (like C<(?:a|b|c)>). This policy complains if
98             you have more than one instance of a single character in an
99             alternation. So C<(?:a|the)> is allowed, but C<(?:a|e|i|o|u)> is not.
100              
101              
102             =head1 CONFIGURATION
103              
104             This Policy is not configurable except for the standard options.
105              
106              
107             =head1 CREDITS
108              
109             Initial development of this policy was supported by a grant from the
110             Perl Foundation.
111              
112              
113             =head1 AUTHOR
114              
115             Chris Dolan <cdolan@cpan.org>
116              
117              
118             =head1 COPYRIGHT
119              
120             Copyright (c) 2007-2023 Chris Dolan
121              
122             This program is free software; you can redistribute it and/or modify
123             it under the same terms as Perl itself. The full text of this license
124             can be found in the LICENSE file included with this module
125              
126             =cut
127              
128             # Local Variables:
129             # mode: cperl
130             # cperl-indent-level: 4
131             # fill-column: 78
132             # indent-tabs-mode: nil
133             # c-indentation-style: bsd
134             # End:
135             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :