Modified source files and compiled any and armel versions of packages
[pkg-perl] / deb-src / libperl-critic-perl / libperl-critic-perl-1.088 / lib / Perl / Critic / Policy / RegularExpressions / ProhibitEscapedMetacharacters.pm
1 ##############################################################################
2 #      $URL: http://perlcritic.tigris.org/svn/perlcritic/trunk/Perl-Critic/lib/Perl/Critic/Policy/RegularExpressions/ProhibitEscapedMetacharacters.pm $
3 #     $Date: 2008-07-03 10:19:10 -0500 (Thu, 03 Jul 2008) $
4 #   $Author: clonezone $
5 # $Revision: 2489 $
6 ##############################################################################
7
8 package Perl::Critic::Policy::RegularExpressions::ProhibitEscapedMetacharacters;
9
10 use 5.006001;
11 use strict;
12 use warnings;
13 use Readonly;
14
15 use English qw(-no_match_vars);
16 use List::MoreUtils qw(any);
17
18 use Perl::Critic::Utils qw{ :booleans :severities hashify };
19 use Perl::Critic::Utils::PPIRegexp qw{ ppiify parse_regexp };
20 use base 'Perl::Critic::Policy';
21
22 our $VERSION = '1.088';
23
24 #-----------------------------------------------------------------------------
25
26 Readonly::Scalar my $DESC => q{Use character classes for literal metachars instead of escapes};
27 Readonly::Scalar my $EXPL => [247];
28
29 Readonly::Hash my %REGEXP_METACHARS =>
30     hashify split m/ /xms, '{ } ( ) . * + ? |'; ##no critic(Interpolation)
31
32 #-----------------------------------------------------------------------------
33
34 sub supported_parameters { return qw()                    }
35 sub default_severity     { return $SEVERITY_LOWEST        }
36 sub default_themes       { return qw( core pbp cosmetic ) }
37 sub applies_to           { return qw(PPI::Token::Regexp::Match
38                                      PPI::Token::Regexp::Substitute
39                                      PPI::Token::QuoteLike::Regexp) }
40
41 #-----------------------------------------------------------------------------
42
43 sub violates {
44     my ( $self, $elem, undef ) = @_;
45
46     # optimization: don't bother parsing the regexp if there are no escapes
47     return if $elem !~ m/\\/xms;
48
49     my $re = ppiify(parse_regexp($elem));
50     return if !$re;
51
52     # Must pass a sub to find() because our node classes don't start with PPI::
53     my $exacts = $re->find(sub {$_[1]->isa('Perl::Critic::PPIRegexp::exact')});
54     return if !$exacts;
55     for my $exact (@{$exacts}) {
56        my @escapes = $exact =~ m/\\(.)/gxms;
57        return $self->violation( $DESC, $EXPL, $elem ) if any { $REGEXP_METACHARS{$_} } @escapes;
58     }
59
60     return;  # OK
61 }
62
63 1;
64
65 __END__
66
67 #-----------------------------------------------------------------------------
68
69 =pod
70
71 =for stopwords IPv4
72
73 =head1 NAME
74
75 Perl::Critic::Policy::RegularExpressions::ProhibitEscapedMetacharacters - Use character classes for literal meta-characters instead of escapes.
76
77 =head1 AFFILIATION
78
79 This Policy is part of the core L<Perl::Critic> distribution.
80
81
82 =head1 DESCRIPTION
83
84 Ever heard of leaning toothpick syndrome?  That comes from writing
85 regular expressions that match on characters that are significant in
86 regular expressions.  For example, the expression to match four
87 forward slashes looks like:
88
89     m/\/\/\/\//;
90
91 Well, this policy doesn't solve that problem (write it as C<m{////}>
92 instead!) but solves a related one.  As seen above, the escapes make
93 the expression hard to parse visually.  One solution is to use
94 character classes.  You see, inside of character classes, the only
95 characters that are special are C<\>, C<]>, C<^> and C<->, so you don't need
96 to escape the others.  So instead of the following loose IPv4 address matcher:
97
98     m/ \d+ \. \d+ \. \d+ \. \d+ /x;
99
100 You could write:
101
102     m/ \d+ [.] \d+ [.] \d+ [.] \d+ /x;
103
104 which is certainly more readable, if less recognizable prior the
105 publication of Perl Best Practices.  (Of course, you should really use
106 L<Regexp::Common::net> to match IPv4 addresses!)
107
108 Specifically, this policy forbids backslashes immediately prior to the following characters:
109
110     { } ( ) . * + ? | #
111
112 We make special exception for C<$> because C</[$]/> turns into
113 C</[5.008006/> for Perl 5.8.6.  We also make an exception for C<^>
114 because it has special meaning (negation) in a character class.
115 Finally, C<[> and C<]> are exempt, of course, because they are awkward
116 to represent in character classes.
117
118 Note that this policy does not forbid unnecessary escaping.  So go
119 ahead and (pointlessly) escape C<!> characters.
120
121
122 =head1 CONFIGURATION
123
124 This Policy is not configurable except for the standard options.
125
126
127 =head1 BUGS
128
129 Perl treats C<m/[#]/x> in unexpected ways.
130 I think it's a bug in Perl itself, but am not 100% sure that I have
131 not simply misunderstood...
132
133 This part makes sense:
134
135   "#f" =~ m/[#]f/x;     # match
136   "#f" =~ m/[#]a/x;     # no match
137
138 This doesn't:
139
140   $qr  = qr/f/;
141   "#f" =~ m/[#]$qr/x; # no match
142
143 Neither does this:
144
145   print qr/[#]$qr/x;  # yields '(?x-ism:[#]$qr
146                                 )'
147
148 =head1 CREDITS
149
150 Initial development of this policy was supported by a grant from the Perl Foundation.
151
152 =head1 AUTHOR
153
154 Chris Dolan <cdolan@cpan.org>
155
156 =head1 COPYRIGHT
157
158 Copyright (c) 2007-2008 Chris Dolan.  Many rights reserved.
159
160 This program is free software; you can redistribute it and/or modify
161 it under the same terms as Perl itself.  The full text of this license
162 can be found in the LICENSE file included with this module
163
164 =cut
165
166 # Local Variables:
167 #   mode: cperl
168 #   cperl-indent-level: 4
169 #   fill-column: 78
170 #   indent-tabs-mode: nil
171 #   c-indentation-style: bsd
172 # End:
173 # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :