Login
Add new policy Variables::ProhibitMatchVars
authorChris Dolan <chris+github@chrisdolan.net>
Fri, 27 Jan 2006 03:43:06 +0000 (03:43 +0000)
committerChris Dolan <chris+github@chrisdolan.net>
Fri, 27 Jan 2006 03:43:06 +0000 (03:43 +0000)
14 files changed:
Changes
MANIFEST
MANIFEST.SKIP
README.developer [new file with mode: 0644]
TODO
bin/perlcritic
lib/Perl/Critic.pm
lib/Perl/Critic/Config.pm
lib/Perl/Critic/Policy/Variables/ProhibitMatchVars.pm [new file with mode: 0644]
t/00_modules.t
t/20_policies_variables.t
t/samples/perlcriticrc.all
t/samples/perlcriticrc.levels
t/samples/perlcriticrc.none

diff --git a/Changes b/Changes
index a2c443a..bd718b5 100644 (file)
--- a/Changes
+++ b/Changes
@@ -9,6 +9,9 @@
 
      More documentation edits.
 
+     New Policies:
+     * Variables::ProhibitMatchVars
+
      Bug Fixes:
      * 15295: "## no critic" pragmas too aggresive on compound statements.
 
index 5193054..7abefe2 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -60,6 +60,7 @@ lib/Perl/Critic/Policy/ValuesAndExpressions/RequireNumberSeparators.pm
 lib/Perl/Critic/Policy/ValuesAndExpressions/RequireQuotedHeredocTerminator.pm
 lib/Perl/Critic/Policy/ValuesAndExpressions/RequireUpperCaseHeredocTerminator.pm
 lib/Perl/Critic/Policy/Variables/ProhibitLocalVars.pm
+lib/Perl/Critic/Policy/Variables/ProhibitMatchVars.pm
 lib/Perl/Critic/Policy/Variables/ProhibitPackageVars.pm
 lib/Perl/Critic/Policy/Variables/ProhibitPunctuationVars.pm
 lib/Perl/Critic/Utils.pm
index 1c6b554..9caa34e 100644 (file)
@@ -1,3 +1,5 @@
+README.developer
+
 # Version Control files
 ^\.cvsignore$
 CVS
diff --git a/README.developer b/README.developer
new file mode 100644 (file)
index 0000000..12f96c8
--- /dev/null
@@ -0,0 +1,14 @@
+Steps for adding a new Policy:
+
+ * Create tests in t/20_policies_*.t
+ * Create the .pm in lib/Perl/Critic/Policy/[category]/
+ * If it will be a default policy:
+   - Add it to lib/Perl/Critic/Policy.pm in native_policies()
+   - Add it to t/samples/perlcriticrc.all
+   - Add it to t/samples/perlcriticrc.levels
+   - Add it to t/samples/perlcriticrc.none
+   - Add 9 to the number of tests in t/00_modules.t
+ * Add it to MANIFEST
+ * Add it to the POD in lib/Perl/Critic.pm
+ * Add it to the POD in bin/perlcritic
+ * Mention it in Changes
diff --git a/TODO b/TODO
index b3a7558..eef3f78 100644 (file)
--- a/TODO
+++ b/TODO
@@ -15,8 +15,6 @@ MISC:
  
 BUGS/LIMITATIONS:
 
-- Modules::RequireEndWithOne
-  - Doesn't notice when "## no critic" extends to the end of the file
 - Modules::RequireVersionVar
   - Doesn't enforce three-part versions
 - NamingConventions::ProhibitAmbiguousNames
index b5a3a23..1cf2113 100755 (executable)
@@ -813,6 +813,10 @@ Write C< <<'THE_END'; > instead of C< <<'theEnd'; > [Severity 1]
 
 Use C<my> instead of C<local>, except when you have to. [Severity 2]
 
+=head2 L<Perl::Critic::Policy::Variables::ProhibitMatchVars>
+
+Avoid C<$`>, C<$&>, C<$'> and their English equivalents. [Severity 4]
+
 =head2 L<Perl::Critic::Policy::Variables::ProhibitPackageVars>
 
 Eliminate globals declared with C<our> or C<use vars> [Severity 3]
index 585142f..1417fd5 100755 (executable)
@@ -657,6 +657,10 @@ Write C< <<'THE_END'; > instead of C< <<'theEnd'; > [Severity 1]
 
 Use C<my> instead of C<local>, except when you have to. [Severity 2]
 
+=head2 L<Perl::Critic::Policy::Variables::ProhibitMatchVars>
+
+Avoid C<$`>, C<$&>, C<$'> and their English equivalents. [Severity 4]
+
 =head2 L<Perl::Critic::Policy::Variables::ProhibitPackageVars>
 
 Eliminate globals declared with C<our> or C<use vars> [Severity 3]
index 597e157..76f6cfb 100755 (executable)
@@ -310,6 +310,7 @@ sub native_policies {
       Perl::Critic::Policy::ValuesAndExpressions::RequireQuotedHeredocTerminator
       Perl::Critic::Policy::ValuesAndExpressions::RequireUpperCaseHeredocTerminator
       Perl::Critic::Policy::Variables::ProhibitLocalVars
+      Perl::Critic::Policy::Variables::ProhibitMatchVars
       Perl::Critic::Policy::Variables::ProhibitPackageVars
       Perl::Critic::Policy::Variables::ProhibitPunctuationVars
     );
diff --git a/lib/Perl/Critic/Policy/Variables/ProhibitMatchVars.pm b/lib/Perl/Critic/Policy/Variables/ProhibitMatchVars.pm
new file mode 100644 (file)
index 0000000..bd17c91
--- /dev/null
@@ -0,0 +1,94 @@
+#######################################################################
+#      $URL$
+#     $Date$
+#   $Author$
+# $Revision$
+########################################################################
+
+package Perl::Critic::Policy::Variables::ProhibitMatchVars;
+
+use strict;
+use warnings;
+use Perl::Critic::Utils;
+use Perl::Critic::Violation;
+use base 'Perl::Critic::Policy';
+
+our $VERSION = '0.14';
+$VERSION = eval $VERSION;    ## no critic
+
+#---------------------------------------------------------------------------
+
+my $desc = q{Match variable used};
+my $expl = [ 82 ];
+
+my %forbidden = map {'$'.$_ => 1} (q{`}, q{&}, q{'}, 'MATCH', 'PREMATCH', 'POSTMATCH');
+
+#---------------------------------------------------------------------------
+
+sub default_severity { return $SEVERITY_HIGH }
+sub applies_to {
+    return qw( PPI::Token::Symbol
+               PPI::Statement::Include );
+}
+
+#---------------------------------------------------------------------------
+
+sub violates {
+    my ( $self, $elem, $doc ) = @_;
+    if (_is_use_english($elem) || _is_forbidden_var($elem)) {
+        my $sev = $self->get_severity();
+        return Perl::Critic::Violation->new( $desc, $expl, $elem, $sev );
+    }
+    return;  #ok!
+}
+
+sub _is_use_english {
+    my $elem = shift;
+    $elem->isa('PPI::Statement::Include') || return;
+    $elem->type() eq 'use' || return;
+    $elem->module() eq 'English' || return;
+    return 1 if ($elem =~ m/\A use \s+ English \s* ;\z/xms); # Bare, lacking -no_match_vars
+    return 1 if ($elem =~ m/\$(?:PRE|POST|)MATCH/xms);
+    return;  # either "-no_match_vars" or a specific list
+}
+
+sub _is_forbidden_var {
+    my $elem = shift;
+    $elem->isa('PPI::Token::Symbol') || return;
+    return exists $forbidden{$elem};
+}
+
+1;
+
+__END__
+
+#---------------------------------------------------------------------------
+
+=pod
+
+=head1 NAME
+
+Perl::Critic::Policy::Variables::ProhibitMatchVars
+
+=head1 DESCRIPTION
+
+Using the "match variables" C<$`>, C<$&>, and/or C<$'> can
+significantly degrade the performance of a program.  This policy
+forbids using them or their English equivalents.  It also forbids
+plain C<use English;> so you should instead employ C<use English
+'-no_match_vars';> which avoids the match variables.  See B<perldoc
+English> or PBP page 82 for more information.
+
+=head1 AUTHOR
+
+Chris Dolan <cdolan@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2006 Chris Dolan.  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
index eb75cea..6550258 100755 (executable)
@@ -8,7 +8,7 @@
 use strict;
 use warnings;
 use PPI::Document;
-use Test::More tests => 539;
+use Test::More tests => 548;  # Add 9 for each new policy created
 use English qw(-no_match_vars);
 
 our $VERSION = '0.14';
index 296a19f..1e33688 100755 (executable)
@@ -7,7 +7,7 @@
 
 use strict;
 use warnings;
-use Test::More tests => 8;
+use Test::More tests => 10;
 use Perl::Critic::Config;
 use Perl::Critic;
 
@@ -56,6 +56,34 @@ is( pcritique($policy, \$code), 0, $policy);
 #----------------------------------------------------------------
 
 $code = <<'END_PERL';
+use English;
+ use English qw($PREMATCH) ; 
+use English qw($MATCH);
+use English qw($POSTMATCH);
+$`;
+$&;
+$';
+$PREMATCH;
+$MATCH;
+$POSTMATCH;
+END_PERL
+
+$policy = 'Variables::ProhibitMatchVars';
+is( pcritique($policy, \$code), 10, $policy);
+
+#----------------------------------------------------------------
+
+$code = <<'END_PERL';
+use English qw(-no_match_vars);
+use English qw($EVAL_ERROR);
+END_PERL
+
+$policy = 'Variables::ProhibitMatchVars';
+is( pcritique($policy, \$code), 0, $policy);
+
+#----------------------------------------------------------------
+
+$code = <<'END_PERL';
 our $var1 = 'foo';
 our (%var2, %var3) = 'foo';
 our (%VAR4, $var5) = ();
index d8cfc19..c583eae 100644 (file)
@@ -58,5 +58,6 @@
 [ValuesAndExpressions::RequireQuotedHeredocTerminator]
 [ValuesAndExpressions::RequireUpperCaseHeredocTerminator]
 [Variables::ProhibitLocalVars]
+[Variables::ProhibitMatchVars]
 [Variables::ProhibitPackageVars]
 [Variables::ProhibitPunctuationVars]
index 991cf67..b746fd2 100644 (file)
@@ -195,4 +195,7 @@ severity = 1
 severity = 1
 
 [Subroutines::ProhibitExcessComplexity]
-severity = 1
\ No newline at end of file
+severity = 1
+
+[Variables::ProhibitMatchVars]
+severity = 1
index eafce4a..d15dfb0 100644 (file)
@@ -62,5 +62,6 @@
 [-ValuesAndExpressions::RequireQuotedHeredocTerminator]
 [-ValuesAndExpressions::RequireUpperCaseHeredocTerminator]
 [-Variables::ProhibitLocalVars]
+[-Variables::ProhibitMatchVars]
 [-Variables::ProhibitPackageVars]
 [-Variables::ProhibitPunctuationVars]
\ No newline at end of file