File Coverage

blib/lib/Perl/Critic/Policy/Modules/RequireNoMatchVarsWithUseEnglish.pm
Criterion Covered Total %
statement 24 68 35.2
branch 3 32 9.3
condition 0 15 0.0
subroutine 11 13 84.6
pod 4 5 80.0
total 42 133 31.5


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::Modules::RequireNoMatchVarsWithUseEnglish;
2              
3 40     40   26752 use 5.010001;
  40         162  
4 40     40   245 use strict;
  40         115  
  40         819  
5 40     40   201 use warnings;
  40         102  
  40         953  
6              
7 40     40   221 use Readonly;
  40         109  
  40         2121  
8              
9 40     40   314 use Perl::Critic::Utils qw< :characters :severities >;
  40         164  
  40         2016  
10 40     40   11667 use parent 'Perl::Critic::Policy';
  40         141  
  40         281  
11              
12             our $VERSION = '1.150';
13              
14             #-----------------------------------------------------------------------------
15              
16             Readonly::Scalar my $EXPL =>
17             q{"use English" without the '-no_match_vars' argument degrades performance.'};
18             Readonly::Scalar my $DESC => q{"use English" without '-no_match_vars' argument};
19              
20             #-----------------------------------------------------------------------------
21              
22 89     89 0 1645 sub supported_parameters { return () }
23 74     74 1 313 sub default_severity { return $SEVERITY_LOW }
24 74     74 1 334 sub default_themes { return qw( core performance ) }
25 30     30 1 82 sub applies_to { return 'PPI::Statement::Include' }
26              
27             #-----------------------------------------------------------------------------
28              
29             sub violates {
30 57     57 1 134 my ( $self, $elem, $doc ) = @_;
31              
32             # "require"ing English is kind of useless.
33 57 100       129 return if $elem->type() ne 'use';
34 55 50       1081 return if $elem->module() ne 'English';
35              
36 0           my @elements = $elem->schildren();
37 0           shift @elements; # dump "use"
38 0           shift @elements; # dump "English"
39              
40 0 0         if (not @elements) {
41 0           return $self->violation($DESC, $EXPL, $elem);
42             }
43              
44 0           _skip_version_number( \@elements );
45              
46 0           @elements = _descend_into_parenthesized_list_if_present(@elements);
47              
48 0 0         if (not @elements) {
49 0           return $self->violation($DESC, $EXPL, $elem);
50             }
51              
52 0           my $current_element = $elements[0];
53              
54 0           while ( $current_element ) {
55 0 0 0       if ( $current_element->isa('PPI::Token::Quote') ) {
    0 0        
    0          
56 0 0         return if $current_element->string() eq '-no_match_vars';
57             }
58             elsif ( $current_element->isa('PPI::Token::QuoteLike::Words') ) {
59 0 0         return if $current_element->content() =~ m/-no_match_vars \b/xms;
60             }
61             elsif (
62             not $current_element->isa('PPI::Token::Operator')
63             or $current_element->content() ne $COMMA
64             and $current_element->content() ne $FATCOMMA
65             ) {
66 0           return $self->violation($DESC, $EXPL, $elem);
67             }
68              
69 0           shift @elements;
70 0           $current_element = $elements[0];
71             }
72              
73 0           return $self->violation($DESC, $EXPL, $elem);
74             }
75              
76              
77             sub _skip_version_number {
78 0     0     my ($elements_ref) = @_;
79              
80 0           my $current_element = $elements_ref->[0];
81              
82 0 0 0       if ( $current_element->isa('PPI::Token::Number') ) {
    0 0        
      0        
83 0           shift @{$elements_ref};
  0            
84             }
85             elsif (
86 0           @{$elements_ref} >= 2
87             and $current_element->isa('PPI::Token::Word')
88             and $current_element->content() =~ m/\A v \d+ \z/xms
89             and $elements_ref->[1]->isa('PPI::Token::Number')
90             ) {
91             # The above messy conditional necessary due to PPI not handling
92             # v-strings.
93 0           shift @{$elements_ref};
  0            
94 0           shift @{$elements_ref};
  0            
95             }
96              
97 0           return;
98             }
99              
100             sub _descend_into_parenthesized_list_if_present {
101 0     0     my @elements = @_;
102              
103 0 0         return if not @elements;
104              
105 0           my $current_element = $elements[0];
106              
107 0 0         if ( $current_element->isa('PPI::Structure::List') ) {
108 0           my @grand_children = $current_element->schildren();
109 0 0         if (not @grand_children) {
110 0           return;
111             }
112              
113 0           my $grand_child = $grand_children[0];
114              
115 0 0         if ( $grand_child->isa('PPI::Statement::Expression') ) {
116 0           my @great_grand_children = $grand_child->schildren();
117              
118 0 0         if (not @great_grand_children) {
119 0           return;
120             }
121              
122 0           return @great_grand_children;
123             }
124             else {
125 0           return @grand_children;
126             }
127             }
128              
129 0           return @elements;
130             }
131              
132             1;
133              
134             __END__
135              
136             #-----------------------------------------------------------------------------
137              
138             =pod
139              
140             =head1 NAME
141              
142             Perl::Critic::Policy::Modules::RequireNoMatchVarsWithUseEnglish - C<use English> must be passed a C<-no_match_vars> argument.
143              
144              
145             =head1 AFFILIATION
146              
147             This Policy is part of the core L<Perl::Critic|Perl::Critic>
148             distribution.
149              
150              
151             =head1 DESCRIPTION
152              
153             Due to unfortunate history, if you use the L<English|English> module
154             but don't pass in a C<-no_match_vars> argument, all regular
155             expressions in the entire program, not merely the module in question,
156             suffer a significant performance penalty, even if you only import a
157             subset of the variables.
158              
159             use English; # not ok
160             use English '-no_match_vars'; # ok
161             use English qw< $ERRNO -no_match_vars >; # ok
162             use English qw($OS_ERROR); # not ok
163              
164             In the last example above, while the match variables aren't loaded
165             into your namespace, they are still created in the C<English>
166             namespace and you still pay the cost.
167              
168              
169             =head1 CONFIGURATION
170              
171             This Policy is not configurable except for the standard options.
172              
173              
174             =head1 AUTHOR
175              
176             Elliot Shank C<< <perl@galumph.com> >>
177              
178              
179             =head1 COPYRIGHT
180              
181             Copyright (c) 2008-2011 Elliot Shank.
182              
183             This program is free software; you can redistribute it and/or modify
184             it under the same terms as Perl itself. The full text of this license
185             can be found in the LICENSE file included with this module.
186              
187              
188             =cut
189              
190             # Local Variables:
191             # mode: cperl
192             # cperl-indent-level: 4
193             # fill-column: 78
194             # indent-tabs-mode: nil
195             # c-indentation-style: bsd
196             # End:
197             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :