File Coverage

blib/lib/Perl/Critic/Policy/ValuesAndExpressions/ProhibitMagicNumbers.pm
Criterion Covered Total %
statement 158 165 95.7
branch 89 116 76.7
condition 21 26 80.7
subroutine 22 22 100.0
pod 6 7 85.7
total 296 336 88.1


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::ValuesAndExpressions::ProhibitMagicNumbers;
2              
3 40     40   30715 use 5.010001;
  40         173  
4 40     40   244 use strict;
  40         98  
  40         900  
5 40     40   238 use warnings;
  40         108  
  40         1103  
6              
7 40     40   225 use Readonly;
  40         128  
  40         2304  
8              
9 40     40   311 use Perl::Critic::Utils qw{ :booleans :characters :severities :data_conversion };
  40         117  
  40         2187  
10              
11 40     40   14406 use parent 'Perl::Critic::Policy';
  40         107  
  40         228  
12              
13             our $VERSION = '1.146';
14              
15             #----------------------------------------------------------------------------
16              
17             Readonly::Scalar my $EXPL =>
18             q{Unnamed numeric literals make code less maintainable};
19             Readonly::Scalar my $USE_READONLY_OR_CONSTANT =>
20             ' Use the Readonly or Const::Fast module or the "constant" pragma instead';
21             Readonly::Scalar my $TYPE_NOT_ALLOWED_SUFFIX =>
22             ") are not allowed.$USE_READONLY_OR_CONSTANT";
23              
24             Readonly::Scalar my $UNSIGNED_NUMBER =>
25             qr{
26             \d+ (?: [$PERIOD] \d+ )? # 1, 1.5, etc.
27             | [$PERIOD] \d+ # .3, .7, etc.
28             }xms;
29             Readonly::Scalar my $SIGNED_NUMBER => qr/ [-+]? $UNSIGNED_NUMBER /xms;
30              
31             Readonly::Scalar my $RANGE =>
32             qr{
33             \A
34             ($SIGNED_NUMBER)
35             [$PERIOD] [$PERIOD]
36             ($SIGNED_NUMBER)
37             (?:
38             [$COLON] by [$LEFT_PAREN]
39             ($UNSIGNED_NUMBER)
40             [$RIGHT_PAREN]
41             )?
42             \z
43             }xms;
44              
45             Readonly::Scalar my $SPECIAL_ARRAY_SUBSCRIPT_EXEMPTION => -1;
46              
47             #----------------------------------------------------------------------------
48              
49             sub supported_parameters {
50             return (
51             {
52 217     217 0 5343 name => 'allowed_values',
53             description => 'Individual and ranges of values to allow, and/or "all_integers".',
54             default_string => '0 1 2',
55             parser => \&_parse_allowed_values,
56             },
57             {
58             name => 'allowed_types',
59             description => 'Kind of literals to allow.',
60             default_string => 'Float',
61             behavior => 'enumeration',
62             enumeration_values => [ qw{ Binary Exp Float Hex Octal } ],
63             enumeration_allow_multiple_values => 1,
64             },
65             {
66             name => 'allow_to_the_right_of_a_fat_comma',
67             description =>
68             q[Should anything to the right of a "=>" be allowed?],
69             default_string => '1',
70             behavior => 'boolean',
71             },
72             {
73             name => 'constant_creator_subroutines',
74             description => q{Names of subroutines that create constants},
75             behavior => 'string list',
76             list_always_present_values => [
77             qw<
78             Readonly Readonly::Scalar Readonly::Array Readonly::Hash
79             const
80             >,
81             ],
82             },
83             );
84             }
85              
86 121     121 1 545 sub default_severity { return $SEVERITY_LOW }
87 74     74 1 395 sub default_themes { return qw( core maintenance certrec ) }
88 125     125 1 427 sub applies_to { return 'PPI::Token::Number' }
89              
90 129     129 1 354 sub default_maximum_violations_per_document { return 10; }
91              
92             #----------------------------------------------------------------------------
93              
94             sub initialize_if_enabled {
95 148     148 1 403 my ($self, $config) = @_;
96              
97 148         682 $self->_determine_checked_types();
98              
99 148         534 return $TRUE;
100             }
101              
102             sub _parse_allowed_values {
103 215     215   763 my ($self, $parameter, $config_string) = @_;
104              
105 215         852 my ( $all_integers_allowed, $allowed_values )
106             = _determine_allowed_values($config_string);
107              
108 215         604 my $allowed_string = ' is not one of the allowed literal values (';
109 215 100       845 if ($all_integers_allowed) {
110 7         22 $allowed_string .= 'all integers';
111              
112 7 100       11 if ( %{$allowed_values} ) {
  7         23  
113 2         6 $allowed_string .= ', ';
114             }
115             }
116             $allowed_string
117 215         597 .= ( join ', ', sort { $a <=> $b } keys %{$allowed_values} ) . ').'
  683         2648  
  215         1692  
118             . $USE_READONLY_OR_CONSTANT;
119              
120 215         764 $self->{_allowed_values} = $allowed_values;
121 215         607 $self->{_all_integers_allowed} = $all_integers_allowed;
122 215         642 $self->{_allowed_string} = $allowed_string;
123              
124 215         746 return;
125             }
126              
127             sub _determine_allowed_values {
128 215     215   676 my ($config_string) = @_;
129              
130 215         611 my @allowed_values;
131             my @potential_allowed_values;
132 215         522 my $all_integers_allowed = 0;
133              
134 215 100       830 if ( defined $config_string ) {
135             my @allowed_values_strings =
136 31         143 grep {$_} split m/\s+/xms, $config_string;
  42         134  
137              
138 31         90 foreach my $value_string (@allowed_values_strings) {
139 40 100       506 if ($value_string eq 'all_integers') {
    100          
    50          
140 7         18 $all_integers_allowed = 1;
141             } elsif ( $value_string =~ m/ \A $SIGNED_NUMBER \z /xms ) {
142 25         105 push @potential_allowed_values, $value_string + 0;
143             } elsif ( $value_string =~ m/$RANGE/xms ) {
144 8         42 my ( $minimum, $maximum, $increment ) = ($1, $2, $3);
145 8   100     43 $increment ||= 1;
146              
147 8         21 $minimum += 0;
148 8         16 $maximum += 0;
149 8         20 $increment += 0;
150              
151 8         28 for ( ## no critic (ProhibitCStyleForLoops)
152             my $value = $minimum;
153             $value <= $maximum;
154             $value += $increment
155             ) {
156 48         116 push @potential_allowed_values, $value;
157             }
158             } else {
159 0         0 die q{Invalid value for allowed_values: }, $value_string,
160             q{. Must be a number, a number range, or},
161             qq{ "all_integers".\n};
162             }
163             }
164              
165 31 100       92 if ($all_integers_allowed) {
166 7         21 @allowed_values = grep { $_ != int $_ } @potential_allowed_values; ## no critic ( BuiltinFunctions::ProhibitUselessTopic )
  7         23  
167             } else {
168 24         69 @allowed_values = @potential_allowed_values;
169             }
170             } else {
171 184         605 @allowed_values = (2);
172             }
173              
174 215 100       823 if ( not $all_integers_allowed ) {
175 208         563 push @allowed_values, 0, 1;
176             }
177 215         970 my %allowed_values = hashify(@allowed_values);
178              
179 215         1035 return ( $all_integers_allowed, \%allowed_values );
180             }
181              
182             sub _determine_checked_types {
183 148     148   378 my ($self) = @_;
184              
185 148         1056 my %checked_types = (
186             'PPI::Token::Number::Binary' => 'Binary literals (',
187             'PPI::Token::Number::Float' => 'Floating-point literals (',
188             'PPI::Token::Number::Exp' => 'Exponential literals (',
189             'PPI::Token::Number::Hex' => 'Hexadecimal literals (',
190             'PPI::Token::Number::Octal' => 'Octal literals (',
191             'PPI::Token::Number::Version' => 'Version literals (',
192             );
193              
194             # This will be set by the enumeration behavior specified in
195             # supported_parameters() above.
196 148         413 my $allowed_types = $self->{_allowed_types};
197              
198 148         382 foreach my $allowed_type ( keys %{$allowed_types} ) {
  148         677  
199 144         605 delete $checked_types{"PPI::Token::Number::$allowed_type"};
200              
201 144 100       543 if ( $allowed_type eq 'Exp' ) {
202              
203             # because an Exp isa(Float).
204 2         4 delete $checked_types{'PPI::Token::Number::Float'};
205             }
206             }
207              
208 148         451 $self->{_checked_types} = \%checked_types;
209              
210 148         361 return;
211             }
212              
213              
214             sub violates {
215 294     294 1 739 my ( $self, $elem, undef ) = @_;
216              
217 294 100       871 if ( $self->{_allow_to_the_right_of_a_fat_comma} ) {
218 276 100       736 return if _element_is_to_the_right_of_a_fat_comma($elem);
219             }
220              
221 271 100       3172 return if _element_is_in_an_include_readonly_or_version_statement(
222             $self, $elem,
223             );
224 176 50       435 return if _element_is_in_a_plan_statement($elem);
225 176 100       529 return if _element_is_in_a_constant_subroutine($elem);
226 174 100       563 return if _element_is_a_package_statement_version_number($elem);
227              
228 172         640 my $literal = $elem->literal();
229 172 100 100     4923 if (
      66        
      100        
      100        
      100        
230             defined $literal
231             and not (
232             $self->{_all_integers_allowed}
233             and int $literal == $literal
234             )
235             and not defined $self->{_allowed_values}{$literal}
236             and not (
237             _element_is_sole_component_of_a_subscript($elem)
238             and $literal == $SPECIAL_ARRAY_SUBSCRIPT_EXEMPTION
239             )
240             ) {
241             return
242             $self->violation(
243             $elem->content() . $self->{_allowed_string},
244 37         128 $EXPL,
245             $elem,
246             );
247             }
248              
249              
250 135         298 my ( $number_type, $type_string );
251              
252 135         242 while (
253 776         2316 ( $number_type, $type_string ) = ( each %{ $self->{_checked_types} } )
254             ) {
255 651 100       2275 if ( $elem->isa($number_type) ) {
256             return
257 10         42 $self->violation(
258             $type_string . $elem->content() . $TYPE_NOT_ALLOWED_SUFFIX,
259             $EXPL,
260             $elem,
261             );
262             }
263             }
264              
265 125         504 return;
266             }
267              
268             sub _element_is_to_the_right_of_a_fat_comma {
269 276     276   574 my ($elem) = @_;
270              
271 276 100       1058 my $previous = $elem->sprevious_sibling() or return;
272              
273 213 100       8248 $previous->isa('PPI::Token::Operator') or return;
274              
275 204         643 return $previous->content() eq q[=>];
276             }
277              
278             sub _element_is_sole_component_of_a_subscript {
279 38     38   102 my ($elem) = @_;
280              
281 38         149 my $parent = $elem->parent();
282 38 100 66     431 if ( $parent and $parent->isa('PPI::Statement::Expression') ) {
283 13 100       46 if ( $parent->schildren() > 1 ) {
284 11         315 return 0;
285             }
286              
287 2         33 my $grandparent = $parent->parent();
288 2 50 33     24 if (
289             $grandparent
290             and $grandparent->isa('PPI::Structure::Subscript')
291             ) {
292 2         17 return 1;
293             }
294             }
295              
296 25         140 return 0;
297             }
298              
299             sub _element_is_in_an_include_readonly_or_version_statement {
300 271     271   592 my ($self, $elem) = @_;
301              
302 271         918 my $parent = $elem->parent();
303 271         1730 while ($parent) {
304 888 100       4963 if ( $parent->isa('PPI::Statement') ) {
305 492 100       1705 return 1 if $parent->isa('PPI::Statement::Include');
306              
307 470 100       1547 if ( $parent->isa('PPI::Statement::Variable') ) {
308 58 50       158 if ( $parent->type() eq 'our' ) {
309 58         2751 my @variables = $parent->variables();
310 58 100 66     3358 if (
311             scalar @variables == 1
312             and $variables[0] eq '$VERSION' ## no critic (RequireInterpolationOfMetachars)
313             ) {
314 57         280 return 1;
315             }
316             }
317              
318 1         7 return 0;
319             }
320              
321 412         1080 my $first_token = $parent->first_token();
322 412 100       6580 if ( $first_token->isa('PPI::Token::Word') ) {
    50          
323 48 100       192 if ( $self->{_constant_creator_subroutines}{
324             $first_token->content() } ) {
325 16         132 return 1;
326             }
327             } elsif ($parent->isa('PPI::Structure::Block')) {
328 0         0 return 0;
329             }
330             }
331              
332 792         2452 $parent = $parent->parent();
333             }
334              
335 175         978 return 0;
336             }
337              
338             # Allow "plan tests => 39;".
339              
340             Readonly::Scalar my $PLAN_STATEMENT_MINIMUM_TOKENS => 4;
341              
342             sub _element_is_in_a_plan_statement {
343 176     176   388 my ($elem) = @_;
344              
345 176         414 my $parent = $elem->parent();
346 176 50       983 return 0 if not $parent;
347              
348 176 50       582 return 0 if not $parent->isa('PPI::Statement');
349              
350 176         555 my @children = $parent->schildren();
351 176 100       3932 return 0 if @children < $PLAN_STATEMENT_MINIMUM_TOKENS;
352              
353 139 100       826 return 0 if not $children[0]->isa('PPI::Token::Word');
354 7 50       23 return 0 if $children[0]->content() ne 'plan';
355              
356 0 0       0 return 0 if not $children[1]->isa('PPI::Token::Word');
357 0 0       0 return 0 if $children[1]->content() ne 'tests';
358              
359 0 0       0 return 0 if not $children[2]->isa('PPI::Token::Operator');
360 0 0       0 return 0 if $children[2]->content() ne '=>';
361              
362 0         0 return 1;
363             }
364              
365             sub _element_is_in_a_constant_subroutine {
366 176     176   370 my ($elem) = @_;
367              
368 176         461 my $parent = $elem->parent();
369 176 50       1013 return 0 if not $parent;
370              
371 176 50       593 return 0 if not $parent->isa('PPI::Statement');
372              
373 176         591 my $following = $elem->snext_sibling();
374 176 100       5149 if ($following) {
375 148 100       721 return 0 if not $following->isa('PPI::Token::Structure');
376 68 50       229 return 0 if $following->content() ne $SCOLON;
377 68 50       573 return 0 if $following->snext_sibling();
378             }
379              
380 96         2043 my $preceding = $elem->sprevious_sibling();
381 96 100       2633 if ($preceding) {
382 92 100       588 return 0 if not $preceding->isa('PPI::Token::Word');
383 4 100       17 return 0 if $preceding->content() ne 'return';
384 2 50       15 return 0 if $preceding->sprevious_sibling();
385             }
386              
387 6 50       55 return 0 if $parent->snext_sibling();
388 6 100       135 return 0 if $parent->sprevious_sibling();
389              
390 5         101 my $grandparent = $parent->parent();
391 5 50       34 return 0 if not $grandparent;
392              
393 5 100       38 return 0 if not $grandparent->isa('PPI::Structure::Block');
394              
395 2         8 my $greatgrandparent = $grandparent->parent();
396 2 50       15 return 0 if not $greatgrandparent;
397 2 50       9 return 0 if not $greatgrandparent->isa('PPI::Statement::Sub');
398              
399 2         30 return 1;
400             }
401              
402             sub _element_is_a_package_statement_version_number {
403 174     174   419 my ($elem) = @_;
404              
405 174 50       578 my $parent = $elem->statement()
406             or return 0;
407              
408 174 100       3842 $parent->isa( 'PPI::Statement::Package' )
409             or return 0;
410              
411 4 50       15 my $version = $parent->schild( 2 )
412             or return 0;
413              
414 4         96 return $version == $elem;
415             }
416              
417             1;
418              
419             __END__
420              
421             #----------------------------------------------------------------------------
422              
423             =pod
424              
425             =for stopwords
426              
427             =head1 NAME
428              
429             Perl::Critic::Policy::ValuesAndExpressions::ProhibitMagicNumbers - Don't use values that don't explain themselves.
430              
431              
432             =head1 AFFILIATION
433              
434             This Policy is part of the core L<Perl::Critic|Perl::Critic>
435             distribution.
436              
437              
438             =head1 DESCRIPTION
439              
440             What is a "magic number"? A magic number is a number that appears in
441             code without any explanation; e.g. C<$bank_account_balance *=
442             57.492;>. You look at that number and have to wonder where that
443             number came from. Since you don't understand the significance of the
444             number, you don't understand the code.
445              
446             In general, numeric literals other than C<0> or C<1> in should not be used.
447             Use the L<constant|constant> pragma or the L<Readonly|Readonly> or
448             L<Const::Fast|Const::Fast> modules to give a descriptive name to the number.
449              
450             There are, of course, exceptions to when this rule should be applied.
451             One good example is positioning of objects in some container like
452             shapes on a blueprint or widgets in a user interface. In these cases,
453             the significance of a number can readily be determined by context.
454              
455             The maximum number of violations per document for this policy defaults
456             to 10.
457              
458              
459             =head2 Ways in which this module applies this rule.
460              
461             By default, this rule is relaxed in that C<2> is permitted to allow
462             for common things like alternation, the STDERR file handle, etc..
463              
464             Numeric literals are allowed in C<use> and C<require> statements to
465             allow for things like Perl version restrictions and
466             L<Test::More|Test::More> plans. Declarations of C<$VERSION> package
467             variables are permitted. Use of C<Readonly>, C<Readonly::Scalar>,
468             C<Readonly::Array>, and C<Readonly::Hash> from the
469             L<Readonly|Readonly> module are obviously valid, but use of
470             C<Readonly::Scalar1>, C<Readonly::Array1>, and C<Readonly::Hash1> are
471             specifically not supported.
472              
473             Use of binary, exponential, hexadecimal, octal, and version numbers,
474             even for C<0> and C<1>, outside of C<use>/C<require>/C<Readonly>
475             statements aren't permitted (but you can change this).
476              
477             There is a special exemption for accessing the last element of an
478             array, i.e. C<$x[-1]>.
479              
480              
481             $x = 0; # ok
482             $x = 0.0; # ok
483             $x = 1; # ok
484             $x = 1.0; # ok
485             $x = 1.5; # not ok
486             $x = 0b0 # not ok
487             $x = 0b1 # not ok
488             $x = 0x00 # not ok
489             $x = 0x01 # not ok
490             $x = 000 # not ok
491             $x = 001 # not ok
492             $x = 0e1 # not ok
493             $x = 1e1 # not ok
494              
495             $frobnication_factor = 42; # not ok
496             use constant FROBNICATION_FACTOR => 42; # ok
497              
498              
499             use 5.6.1; # ok
500             use Test::More plan => 57; # ok
501             plan tests => 39; # ok
502             our $VERSION = 0.22; # ok
503              
504              
505             $x = $y[-1] # ok
506             $x = $y[-2] # not ok
507              
508              
509              
510             foreach my $solid (1..5) { # not ok
511             ...
512             }
513              
514              
515             use Readonly;
516              
517             Readonly my $REGULAR_GEOMETRIC_SOLIDS => 5;
518              
519             foreach my $solid (1..$REGULAR_GEOMETRIC_SOLIDS) { #ok
520             ...
521             }
522              
523              
524             =head1 CONFIGURATION
525              
526             This policy has four options: C<allowed_values>, C<allowed_types>,
527             C<allow_to_the_right_of_a_fat_comma>, and C<constant_creator_subroutines>.
528              
529              
530             =head2 C<allowed_values>
531              
532             The C<allowed_values> parameter is a whitespace delimited set of
533             permitted number I<values>; this does not affect the permitted formats
534             for numbers. The defaults are equivalent to having the following in
535             your F<.perlcriticrc>:
536              
537             [ValuesAndExpressions::ProhibitMagicNumbers]
538             allowed_values = 0 1 2
539              
540             Note that this policy forces the values C<0> and C<1> into the
541             permitted values. Thus, specifying no values,
542              
543             allowed_values =
544              
545             is the same as simply listing C<0> and C<1>:
546              
547             allowed_values = 0 1
548              
549             The special C<all_integers> value, not surprisingly, allows all
550             integral values to pass, subject to the restrictions on number types.
551              
552             Ranges can be specified as two (possibly fractional) numbers separated
553             by two periods, optionally suffixed with an increment using the Perl 6
554             C<:by()> syntax. E.g.
555              
556             allowed_values = 7..10
557              
558             will allow 0, 1, 7, 8, 9, and 10 as literal values. Using fractional
559             values like so
560              
561             allowed_values = -3.5..-0.5:by(0.5)
562              
563             will permit -3.5, -3, -2.5, -2, -2.5, -1, -0.5, 0, and 1.
564             Unsurprisingly, the increment defaults to 1, which means that
565              
566             allowed_values = -3.5..-0.5
567              
568             will make -3.5, -2.5, -2.5, -0.5, 0, and 1 valid.
569              
570             Ranges are not lazy, i.e. you'd better have a lot of memory available
571             if you use a range of C<1..1000:by(0.01)>. Also remember that all of
572             this is done using floating-point math, which means that
573             C<1..10:by(0.3333)> is probably not going to be very useful.
574              
575             Specifying an upper limit that is less than the lower limit will
576             result in no values being produced by that range. Negative increments
577             are not permitted.
578              
579             Multiple ranges are permitted.
580              
581             To put this all together, the following is a valid, though not likely
582             to be used, F<.perlcriticrc> entry:
583              
584             [ValuesAndExpressions::ProhibitMagicNumbers]
585             allowed_values = 3.1415269 82..103 -507.4..57.8:by(0.2) all_integers
586              
587              
588             =head2 C<allowed_types>
589              
590             The C<allowed_types> parameter is a whitespace delimited set of
591             subclasses of L<PPI::Token::Number|PPI::Token::Number>.
592              
593             Decimal integers are always allowed. By default, floating-point
594             numbers are also allowed.
595              
596             For example, to allow hexadecimal literals, you could configure this
597             policy like
598              
599             [ValuesAndExpressions::ProhibitMagicNumbers]
600             allowed_types = Hex
601              
602             but without specifying anything for C<allowed_values>, the allowed
603             hexadecimal literals will be C<0x00>, C<0x01>, and C<0x02>. Note,
604             also, as soon as you specify a value for this parameter, you must
605             include C<Float> in the list to continue to be able to use floating
606             point literals. This effect can be used to restrict literals to only
607             decimal integers:
608              
609             [ValuesAndExpressions::ProhibitMagicNumbers]
610             allowed_types =
611              
612             If you permit exponential notation, you automatically also allow
613             floating point values because an exponential is a subclass of
614             floating-point in L<PPI|PPI>.
615              
616              
617             =head2 C<allow_to_the_right_of_a_fat_comma>
618              
619             If this is set, you can put any number to the right of a fat comma.
620              
621             my %hash = ( a => 4512, b => 293 ); # ok
622             my $hash_ref = { a => 4512, b => 293 }; # ok
623             some_subroutine( a => 4512, b => 293 ); # ok
624              
625             Currently, this only means I<directly> to the right of the fat comma. By
626             default, this value is I<true>.
627              
628              
629             =head2 C<constant_creator_subroutines>
630              
631             This parameter allows you to specify the names of subroutines that create
632             constants, in addition to C<Readonly>, C<Const::Fast>, and friends. For
633             example, if you use a custom C<Const::Fast>-like module that supports a
634             C<create_constant> subroutine to create constants, you could add something
635             like the following to your F<.perlcriticrc>:
636              
637             [ValuesAndExpressions::ProhibitMagicNumbers]
638             constant_creator_subroutines = create_constant
639              
640             If you have more than one name to add, separate them by whitespace.
641              
642             The subroutine name should appear exactly as it is in your code. For example,
643             if your code does not import the creating subroutine
644             subroutine, you would need to configure this policy as something like
645              
646             [ValuesAndExpressions::ProhibitMagicNumbers]
647             constant_creator_subroutines = create_constant Constant::Create::create_constant
648              
649              
650             =head1 BUGS
651              
652             There is currently no way to permit version numbers in regular code,
653             even if you include them in the C<allowed_types>. Some may actually
654             consider this a feature.
655              
656              
657             =head1 AUTHOR
658              
659             Elliot Shank C<< <perl@galumph.com> >>
660              
661              
662             =head1 COPYRIGHT
663              
664             Copyright (c) 2006-2011 Elliot Shank.
665              
666             This program is free software; you can redistribute it and/or modify
667             it under the same terms as Perl itself. The full text of this license
668             can be found in the LICENSE file included with this module.
669              
670             =cut
671              
672             # Local Variables:
673             # mode: cperl
674             # cperl-indent-level: 4
675             # fill-column: 78
676             # indent-tabs-mode: nil
677             # c-indentation-style: bsd
678             # End:
679             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :