Login
RT #72660: Exclude pragmas from Modules::RequireExplicitPackage
authorTom Wyant <harryfmudd@comcast.net>
Mon, 5 Dec 2011 20:03:31 +0000 (20:03 +0000)
committerTom Wyant <harryfmudd@comcast.net>
Mon, 5 Dec 2011 20:03:31 +0000 (20:03 +0000)
This commit does not do what the original request asked for, but does
allow the user to specify modules which are allowed to be imported
before the 'package' statement. The configuration option is
'allow_import_of' (for the moment -- I'm sure someone can think of a
better name), and by default it allows nothing.

Changes
lib/Perl/Critic/Policy/Modules/RequireExplicitPackage.pm
t/Modules/RequireExplicitPackage.run

diff --git a/Changes b/Changes
index fd7e0b8..35688fb 100644 (file)
--- a/Changes
+++ b/Changes
@@ -11,6 +11,9 @@ Next release, whenever it is:
       '//=', '<<=', and '>>=' are assignment operators. RT #70901.
     * ErrorHandling::RequireCheckingReturnValueOfEval now allows things
       like grep { eval $_ }. RT #69489.
+    * Modules::RequireExplicitPackage now has configuraion option
+      allow_import_of, to allow the import of specified modules before
+      the package statement. RT #72660.
     * RegularExpressions::ProhibitEnumeratedClasses no longer thinks
       that [A-Za-z_] matches \w. RT #69322.
     * RegularExpressions::ProhibitUnusedCaptures now skips the first
index dcf96b3..5f2a12a 100644 (file)
@@ -12,7 +12,7 @@ use strict;
 use warnings;
 use Readonly;
 
-use Perl::Critic::Utils qw{ :severities :classification };
+use Perl::Critic::Utils qw{ :booleans :severities :classification };
 use base 'Perl::Critic::Policy';
 
 our $VERSION = '1.116';
@@ -32,6 +32,11 @@ sub supported_parameters {
             default_string => '1',
             behavior       => 'boolean',
         },
+        {
+            name           => 'allow_import_of',
+            description    => q{Allow the specified modules to be imported outside a package},
+            behavior       => 'string list',
+        },
     );
 }
 
@@ -59,7 +64,9 @@ sub violates {
     # Find all statements that aren't 'package' statements
     my $stmnts_ref = $doc->find( 'PPI::Statement' );
     return if !$stmnts_ref;
-    my @non_packages = grep { !$_->isa('PPI::Statement::Package') } @{$stmnts_ref};
+    my @non_packages = grep {
+        $self->_is_statement_of_interest( $_ )
+    } @{$stmnts_ref};
     return if !@non_packages;
 
     # If the 'package' statement is not defined, or the other
@@ -76,6 +83,25 @@ sub violates {
     return @viols;
 }
 
+sub _is_statement_of_interest {
+    my ( $self, $elem ) = @_;
+
+    $elem
+        or return $FALSE;
+
+    $elem->isa( 'PPI::Statement::Package' )
+        and return $FALSE;
+
+    if ( $elem->isa( 'PPI::Statement::Include' ) ) {
+        if ( defined( my $module = $elem->module() ) ) {
+            $self->{_allow_import_of}{$module}
+                and return $FALSE;
+        }
+    }
+
+    return $TRUE;
+}
+
 1;
 
 __END__
@@ -123,6 +149,19 @@ F<.perlcriticrc> file
     [Modules::RequireExplicitPackage]
     exempt_scripts = 0
 
+Some users may find it desirable to exempt the load of specific modules
+from this policy. For example, Perl does not support Unicode module
+names because of portability problems. Users who are not concerned about
+this and intend to use C<UTF-8> module names will need to specify
+C<use utf8;> before the package declaration. To do this, add the
+following to your F<.perlcriticrc> file
+
+    [Modules::RequireExplicitPackage]
+    allow_import_of = utf8
+
+The C<allow_import_of> configuration option takes multiple module names,
+separated by spaces.
+
 
 =head1 IMPORTANT CHANGES
 
index 565d72e..823c0c2 100644 (file)
@@ -109,6 +109,17 @@ $foo = $bar;
 
 #-----------------------------------------------------------------------------
 
+## name Allow exception for specific module loads. RT #72660
+## failures 0
+## parms { allow_import_of => 'utf8' }
+## cut
+
+use utf8;
+
+package Foo::Bar;
+
+#-----------------------------------------------------------------------------
+
 ##############################################################################
 #      $URL$
 #     $Date$