Login
New policy: ValuesAndExpressions::ProhibitMagicNumbers
authorElliot Shank <perl@galumph.com>
Sun, 12 Nov 2006 06:21:28 +0000 (06:21 +0000)
committerElliot Shank <perl@galumph.com>
Sun, 12 Nov 2006 06:21:28 +0000 (06:21 +0000)
Changes
MANIFEST
MANIFEST.SKIP
README.developer
lib/Perl/Critic/Policy/ValuesAndExpressions/ProhibitMagicNumbers.pm [new file with mode: 0644]
lib/Perl/Critic/PolicyFactory.pm
lib/Perl/Critic/PolicySummary.pod
t/20_policies_prohibitmagicnumbers.t [new file with mode: 0644]

diff --git a/Changes b/Changes
index 57e4cc2..132dc82 100644 (file)
--- a/Changes
+++ b/Changes
@@ -10,6 +10,7 @@ Hackathon:
      New Policies:
      * Editor::RequireEmacsFileVariables
      * TestingAndDebugging::ProhibitProlongedStrictureOverride
+     * ValuesAndExpressions::ProhibitMagicNumbers (needs customizability)
      * Variables::ProhibitListProcessingSideEffects (not quite finished)
 
 [0.21]  Released on 2006-11-05
index 4b00cc7..7740b72 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -85,6 +85,7 @@ lib/Perl/Critic/Policy/ValuesAndExpressions/ProhibitEmptyQuotes.pm
 lib/Perl/Critic/Policy/ValuesAndExpressions/ProhibitEscapedCharacters.pm
 lib/Perl/Critic/Policy/ValuesAndExpressions/ProhibitInterpolationOfLiterals.pm
 lib/Perl/Critic/Policy/ValuesAndExpressions/ProhibitLeadingZeros.pm
+lib/Perl/Critic/Policy/ValuesAndExpressions/ProhibitMagicNumbers.pm
 lib/Perl/Critic/Policy/ValuesAndExpressions/ProhibitMismatchedOperators.pm
 lib/Perl/Critic/Policy/ValuesAndExpressions/ProhibitMixedBooleanOperators.pm
 lib/Perl/Critic/Policy/ValuesAndExpressions/ProhibitNoisyQuotes.pm
@@ -138,6 +139,7 @@ t/20_policies_inputoutput.t
 t/20_policies_miscellanea.t
 t/20_policies_modules.t
 t/20_policies_namingconventions.t
+t/20_policies_prohibitmagicnumbers.t
 t/20_policies_references.t
 t/20_policies_regularexpressions.t
 t/20_policies_subroutines.t
index 27ac98f..a64ada1 100644 (file)
@@ -48,10 +48,12 @@ RCS
 \.tmp$
 \.\#.+
 \#$
+\.swp$
 
 # Mac/SMB files
 \.DS_Store
 ^\._.+
+\bIcon\x0d
 
 # Flash development
 \.swd$
index f2296c3..e24a2e4 100644 (file)
@@ -3,7 +3,7 @@ Steps for adding a new Policy:
  * Create tests in t/20_policies_[category].t
  * Create the .pm in lib/Perl/Critic/Policy/[category]/[name].pm
  * If it will be a default policy:
-   - Add it to lib/Perl/Critic/Config.pm in native_policies()
+   - Add it to lib/Perl/Critic/PolicyFactory.pm in native_policies()
    - Add 14 to the number of tests in t/00_modules.t
  * If it applies_to() PPI::Document, perhaps add an exception in t/03_pragmas.t
  * Add it to MANIFEST (via "Build manifest")
diff --git a/lib/Perl/Critic/Policy/ValuesAndExpressions/ProhibitMagicNumbers.pm b/lib/Perl/Critic/Policy/ValuesAndExpressions/ProhibitMagicNumbers.pm
new file mode 100644 (file)
index 0000000..a13c82b
--- /dev/null
@@ -0,0 +1,156 @@
+package Perl::Critic::Policy::ValuesAndExpressions::ProhibitMagicNumbers;
+
+use strict;
+use warnings;
+use Perl::Critic::Utils;
+use base 'Perl::Critic::Policy';
+
+our $VERSION = 0.21;
+
+#----------------------------------------------------------------------------
+
+my $desc = q{Numeric literals make code less maintainable};
+my %allowed = hashify( 0, 1, 2 );   # Should be configurable
+
+#----------------------------------------------------------------------------
+
+sub default_severity { return $SEVERITY_LOW        }
+sub default_themes   { return qw( readability )    }
+sub applies_to       { return 'PPI::Token::Number' }
+
+#----------------------------------------------------------------------------
+
+sub violates {
+    my ( $self, $elem, undef ) = @_;
+
+    return if _element_is_in_an_include_or_readonly_statement($elem);
+
+    my @violation = ( $desc, undef, $elem );
+
+    my $literal = $elem->literal();
+    return $self->violation(@violation)
+        if defined $literal and not defined $allowed{ $literal };
+
+    if (
+            $elem->isa('PPI::Token::Number::Binary')
+        or  $elem->isa('PPI::Token::Number::Hex')
+        or  $elem->isa('PPI::Token::Number::Octal')
+        or  $elem->isa('PPI::Token::Number::Version')
+    ) {
+        return $self->violation(@violation);
+    } # end if
+
+    if (
+            $elem->isa('PPI::Token::Number::Exp')
+        and $elem->content() ne '0E0'
+        and $elem->content() ne '0e0'
+    ) {
+        return $self->violation(@violation);
+    } # end if
+
+    return;
+} # end violates()
+
+sub _element_is_in_an_include_or_readonly_statement {
+    my $elem = shift;
+
+    my $parent = $elem->parent();
+    while ($parent) {
+        if ($parent->isa('PPI::Statement')) {
+            return 1 if $parent->isa('PPI::Statement::Include');
+
+            my $first_token = $parent->first_token();
+            if (
+                    $first_token->isa('PPI::Token::Word')
+                and $first_token eq 'Readonly'
+            ) {
+                return 1;
+            } # end if
+# Uncomment once PPI bug fixed.
+#        } elsif ($parent->isa('PPI::Structure::Block')) {
+#            return 0;
+        } # end if
+
+        $parent = $parent->parent();
+    } # end while
+
+    return 0;
+} # end _element_is_in_an_include_or_readonly_statement()
+
+
+1;
+
+__END__
+
+#----------------------------------------------------------------------------
+
+=pod
+
+=head1 NAME
+
+Perl::Critic::Policy::ValuesAndExpressions::ProhibitMagicNumbers
+
+=head1 DESCRIPTION
+
+Numeric literals other than C<0> or C<1> in the middle of code make it hard to
+maintain because one cannot understand their significance or where they were
+derived from.  Use the L<constant> pragma or the L<Readonly> module to give a
+descriptive name to the number.
+
+Numeric literals are allowed in C<use> statements to allow for things like Perl
+version restrictions and L<Test::More> plans.
+
+The rule is relaxed in that C<2> is permitted to allow for things like
+alternation, the STDERR file handle, etc..
+
+  $x = 0;                                   #ok
+  $x = 0.0;                                 #ok
+  $x = 0_._0_;                              #ok
+  $x = 1;                                   #ok
+  $x = 1.0;                                 #ok
+  $x = 1.5;                                 #not ok
+
+  $frobnication_factor = 42;                #not ok
+  use constant FROBNICATION_FACTOR => 42;   #ok
+
+
+  use 5.6.1;                                #ok
+  use Test::More plan => 57;                #ok
+
+
+  foreach my $solid (1..5) {                #not ok
+      ...
+  }
+
+
+  use Readonly;
+
+  Readonly my $REGULAR_GEOMETRIC_SOLIDS => 5;
+
+  foreach my $solid (1..$REGULAR_GEOMETRIC_SOLIDS) {  #ok
+      ...
+  }
+
+
+=head1 AUTHOR
+
+Elliot Shank C<< <perl@galumph.com> >>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2006 Elliot Shank.  All rights reserved.
+
+This program is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.  The full text of this license
+can be found in the LICENSE file included with this module.
+
+=cut
+
+# Local Variables:
+#   mode: cperl
+#   cperl-indent-level: 4
+#   fill-column: 78
+#   indent-tabs-mode: nil
+#   c-indentation-style: bsd
+# End:
+# ex: set ts=8 sts=4 sw=4 expandtab
index de4ec2b..9946936 100644 (file)
@@ -246,6 +246,7 @@ sub native_policy_names {
       Perl::Critic::Policy::ValuesAndExpressions::ProhibitEscapedCharacters
       Perl::Critic::Policy::ValuesAndExpressions::ProhibitInterpolationOfLiterals
       Perl::Critic::Policy::ValuesAndExpressions::ProhibitLeadingZeros
+      Perl::Critic::Policy::ValuesAndExpressions::ProhibitMagicNumbers
       Perl::Critic::Policy::ValuesAndExpressions::ProhibitMismatchedOperators
       Perl::Critic::Policy::ValuesAndExpressions::ProhibitMixedBooleanOperators
       Perl::Critic::Policy::ValuesAndExpressions::ProhibitNoisyQuotes
index 6ea8ad5..d3628e6 100644 (file)
@@ -329,6 +329,10 @@ Always use single quotes for literal strings. [Severity 1]
 
 Write C<oct(755)> instead of C<0755> [Severity 5]
 
+=head2 L<Perl::Critic::Policy::ValuesAndExpressions::ProhibitMagicNumbers>
+
+Use L<Readonly> to give meaningful names for numeric literals. [Severity 2]
+
 =head2 L<Perl::Critic::Policy::ValuesAndExpressions::ProhibitMismatchedOperators>
 
 Don't mix numeric operators with string operands, or vice-versa. [Severity 3]
diff --git a/t/20_policies_prohibitmagicnumbers.t b/t/20_policies_prohibitmagicnumbers.t
new file mode 100644 (file)
index 0000000..77e8c3d
--- /dev/null
@@ -0,0 +1,700 @@
+#!perl
+
+use strict;
+use warnings;
+use Test::More tests => 52;
+
+# common P::C testing tools
+use Perl::Critic::TestUtils qw(pcritique);
+Perl::Critic::TestUtils::block_perlcriticrc();
+
+my $policy = 'ValuesAndExpressions::ProhibitMagicNumbers';
+my $code;
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+use 5.8.1;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: version numbers allowed in use statements"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+require 5.8.1;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: version numbers allowed in require statements"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$Aleax = 5.8.1;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    1,
+    "$policy: version numbers not allowed in regular statements"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+use Test::More plan => 57;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: all numbers are allowed on any use statement"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$tangle_tree = 0;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: decimal zero is allowed anywhere"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$xiron_golem = 0.0
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: floating-point zero is allowed anywhere"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$killer_tomato = 1;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: decimal one is allowed anywhere"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$witch_doctor = 1.0;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: floating-point 0 is allowed anywhere"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$soldier = 2.5;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    1,
+    "$policy: fractional numbers not allowed in regular statements"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$frobnication_factor = 42;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    1,
+    "$policy: the answer to life, the universe, and everything is not allowed in regular statements"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+use constant FROBNICATION_FACTOR => 42;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: the answer to life, the universe, and everything is allowed as a constant"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+use constant FROBNICATION_FACTOR => 1_234.567_89;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: fractional numbers are allowed as a constant"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+# "5" is a magic number...
+$code = <<'END_PERL';
+foreach my $solid (1..5) {
+    frobnicate($solid);
+}
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    1,
+    "$policy: magic numbers not allowed in ranges"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+# ... until it's given a name describing its significance.
+$code = <<'END_PERL';
+use Readonly;
+
+Readonly my $REGULAR_GEOMETRIC_SOLIDS => 5;
+
+foreach my $solid (1..$REGULAR_GEOMETRIC_SOLIDS) {
+    frobnicate($solid);
+}
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: readonly numbers allowed in ranges"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$battlemech = 0b0;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    1,
+    "$policy: binary zero isn't allowed in regular statements"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+Readonly $giant_eel => 0b0;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: readonly binary zero is allowed"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$xeroc = 0b1;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    1,
+    "$policy: binary one isn't allowed in regular statements"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+Readonly $creeping_coins => 0b1;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: readonly binary one is allowed"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$basilisk = 000;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    1,
+    "$policy: octal zero isn't allowed in regular statements"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+Readonly $dwarf_lord => 000;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: readonly octal zero is allowed"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$brown_mold = 001;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    1,
+    "$policy: octal one isn't allowed in regular statements"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+Readonly $kobold_zombie => 001;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: readonly octal one is allowed"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$yeti = 0x00;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    1,
+    "$policy: hexadecimal zero isn't allowed in regular statements"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+Readonly $newt => 0x00;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: readonly hexadecimal zero is allowed"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$piranha = 0x01;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    1,
+    "$policy: hexadecimal one isn't allowed in regular statements"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+Readonly $Lord_Surtur => 0x01;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: readonly hexadecimal one is allowed"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$Green_elf = 0e1;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    1,
+    "$policy: exponential zero isn't allowed in regular statements"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+Readonly $sasquatch => 0e1;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: readonly exponential zero is allowed"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$Orion = 0e0;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: special 0e0 is allowed anywhere"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$Uruk_hai = 1e1;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    1,
+    "$policy: exponential one isn't allowed in regular statements"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+Readonly $leather_golem => 1e1;
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: readonly exponential one is allowed"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+use Some::Module [ 1, 2, 3, 4 ];
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: any numbers allowed in array references in use statement"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+require Some::Other::Module [ 1, 2, 3, 4 ];
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: any numbers allowed in array references in require statement"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+Readonly $Totoro => [ 1, 2, 3, 4 ];
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: any numbers allowed in array references in readonly statement"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$Evil_Iggy = [ 1, 2, 3, 4 ];
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    2,
+    "$policy: magic numbers not allowed in array references in regular statement"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$titanothere = [ 1, 0, 1, 0 ];
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: array references containing only good numbers are allowed (by this policy)"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+use Some::Module { 1 => 2, 3 => 4 };
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: any numbers allowed in hash references in use statement"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+require Some::Other::Module { 1 => 2, 3 => 4 };
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: any numbers allowed in hash references in require statement"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+Readonly $Vlad_the_Impaler => { 1 => 2, 3 => 4 };
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: any numbers allowed in hash references in readonly statement"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$gnome_lord = { 1 => 2, 3 => 4 };
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    2,
+    "$policy: magic numbers not allowed in hash references in regular statement"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+$aardvark = { 1 => 0, 0 => 1 };
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: hash references containing only good numbers are allowed (by this policy)"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+use Some::Module ( 1, 2, 3, 4 );
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: any numbers allowed in lists in use statement"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+require Some::Other::Module ( 1, 2, 3, 4 );
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: any numbers allowed in lists in require statement"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+Readonly @elf_mummy => ( 1, 2, 3, 4 );
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: any numbers allowed in lists in readonly statement"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+@kitten = ( 1, 2, 3, 4 );
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    2,
+    "$policy: magic numbers not allowed in lists in regular statement"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+@purple_worm = ( 1, 0, 1, 0 );
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: lists containing only good numbers are allowed (by this policy)"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+@quivering_blob = ( 1, ( 2, 3, 4 ) );
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    2,
+    "$policy: magic numbers not allowed in nested lists in regular statement"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+@green_slime = ( 1, [ 2, 3, 4 ] );
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    2,
+    "$policy: magic numbers not allowed in nested array references in regular statement"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+@fire_elemental = ( 1, { 2 => 4 } );
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    1,
+    "$policy: magic numbers not allowed in nested hash references in regular statement"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+@Y2K_bug = ( 1, { 0 => 1 } );
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: good numbers allowed in nested hash references anywhere"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+@fog_cloud = [ 1, { 0 => { 1 => [ 1, 1, [ \382 ] ] } } ];
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    1,
+    "$policy: magic numbers not allowed in deep datastructures in regular statement"
+);
+
+#----------------------------------------------------------------
+
+# TEST
+$code = <<'END_PERL';
+@fog_cloud = [ 1, { 0 => { 1 => [ 1, 1, [ 1 ] ] } } ];
+END_PERL
+
+is(
+    pcritique($policy, \$code),
+    0,
+    "$policy: good numbers allowed in deep datastructures anywhere"
+);
+
+#----------------------------------------------------------------