On Sun, Jun 22, 2008 at 10:35 PM, Will Coleda via RT
<[EMAIL PROTECTED]> wrote:
> Attached find a first pass at converting our perlcritic.t into using 
> Test::Perl::Critic.
>
> This patch:
>
> - requires Test::Perl::Critic to do anything useful with the test. (We can 
> add it to
> Bundle::Parrot)
> - creates a new perlcritic.conf file that represents declaratively a large 
> chunk of the code we
> used to use to manage the policy list.
> - removes the ability to list the policies. (you have the conf file)
> - removes the ability to specify a specific policy (you can roll your own 
> with themes)
> - removes the ability to specify a directory to run the policies against (but 
> if we do, let's do it
> without File::Find, and just key off the MANIFEST like we do now.)
> - keeps the ability to specify a "group" of tests, but calls it a theme, 
> following the lead set by
> Perl::Critic.
> - reports each file as a test, not each policy.
>
> I think the last item there is a big reason we started down the path we did, 
> but given how
> much simpler this script is, I don't think it's worth worrying about.
>
> I've tested this on Perl::Critic 1.086; I'd be interested to hear feedback on 
> older versions of
> P::C before I apply. (The old version I had installed is no longer available 
> for easy download
> on the CPAN)
>
> Feedback in general, as well: This is a reduction in features from the 
> original version, but I
> think it's a step forward.

It's been 4 days with no negative feedback; I'll plan on applying the
patch this weekend.

> --
> Will "Coke" Coleda
>
> Index: tools/util/perlcritic.conf
> ===================================================================
> --- tools/util/perlcritic.conf  (revision 0)
> +++ tools/util/perlcritic.conf  (revision 0)
> @@ -0,0 +1,65 @@
> +verbose = 3
> +
> +[BuiltinFunctions::ProhibitStringySplit]
> +add_themes = parrot
> +
> +[CodeLayout::ProhibitDuplicateCoda]
> +add_themes = parrot
> +
> +[CodeLayout::ProhibitHardTabs]
> +allow_leading_tabs = 0
> +add_themes = parrot
> +
> +[CodeLayout::ProhibitTrailingWhitespace]
> +add_themes = parrot
> +
> +[CodeLayout::RequireTidyCode]
> +perltidyrc = tools/util/perltidy.conf
> +add_themes = extra
> +
> +[CodeLayout::UseParrotCoda]
> +add_themes = parrot
> +
> +[InputOutput::ProhibitBarewordFileHandles]
> +add_themes = parrot
> +
> +[InputOutput::ProhibitTwoArgOpen]
> +add_themes = parrot
> +
> +[NamingConventions::ProhibitAmbiguousNames]
> +# remove abstract from the list of forbidden names
> +forbid = bases close contract last left no record right second set
> +add_themes = extra
> +
> +[Subroutines::ProhibitBuiltinHomonyms]
> +add_themes = extra
> +
> +[Subroutines::ProhibitExplicitReturnUndef]
> +add_themes = parrot
> +
> +[Subroutines::ProhibitSubroutinePrototypes]
> +add_themes = parrot
> +
> +[Subroutines::RequireFinalReturn]
> +add_themes = extra
> +
> +[TestingAndDebugging::MisplacedShebang]
> +add_themes = parrot
> +
> +[TestingAndDebugging::ProhibitShebangWarningsArg]
> +add_themes = parrot
> +
> +[TestingAndDebugging::RequirePortableShebang]
> +add_themes = parrot
> +
> +[TestingAndDebugging::RequireUseStrict]
> +add_themes = parrot
> +
> +[TestingAndDebugging::RequireUseWarnings]
> +add_themes = parrot
> +
> +[Variables::ProhibitConditionalDeclarations]
> +add_themes = parrot
> +
> +[Bangs::ProhibitFlagComments]
> +add_themes = extra
> Index: MANIFEST
> ===================================================================
> --- MANIFEST    (revision 28654)
> +++ MANIFEST    (working copy)
> @@ -1,7 +1,7 @@
>  # ex: set ro:
>  # $Id$
>  #
> -# generated by tools/dev/mk_manifest_and_skip.pl Sun Jun 22 17:10:01 2008 UT
> +# generated by tools/dev/mk_manifest_and_skip.pl Mon Jun 23 02:21:20 2008 UT
>  #
>  # See tools/dev/install_files.pl for documentation on the
>  # format of this file.
> @@ -3888,6 +3888,7 @@
>  tools/util/dump_pbc.pl                                      []
>  tools/util/gen_release_info.pl                              []
>  tools/util/ncidef2pasm.pl                                   []
> +tools/util/perlcritic.conf                                  []
>  tools/util/perltidy.conf                                    []
>  tools/util/pgegrep                                          []
>  tools/util/release.json                                     []
> Index: t/codingstd/perlcritic.t
> ===================================================================
> --- t/codingstd/perlcritic.t    (revision 28654)
> +++ t/codingstd/perlcritic.t    (working copy)
> @@ -1,256 +1,54 @@
>  #! perl
> -# Copyright (C) 2001-2007, The Perl Foundation.
> +# Copyright (C) 2008, The Perl Foundation.
>  # $Id$
>
>  use strict;
>  use warnings;
>
> -use lib qw(. lib ../lib ../../lib);
> +use lib qw{lib};
>
> -use Fatal qw(open);
> -use File::Find;
>  use File::Spec;
> -use Test::More;
> -use Parrot::Config qw{%PConfig};
> -use Parrot::Distribution;
>  use Getopt::Long;
> +use Parrot::Config qw(%PConfig);
> +use Parrot::Distribution;
> +use Test::More;
>
> -BEGIN {
> -    eval { require Perl::Critic; };
> -    if ($@) {
> -        plan skip_all => 'Perl::Critic not installed';
> -    }
> -    my $required_version = 1.03;
> -    if ( $Perl::Critic::VERSION < $required_version ) {
> -        plan skip_all => "Perl::Critic v$required_version required, 
> v$Perl::Critic::VERSION found";
> -    }
> +eval { require Test::Perl::Critic };
> +if ($@) {
> +  plan( skip_all => 'Test::Perl::Critic required to criticize code');
> +  exit;
>  }
>
> -my $perl_tidy_conf = 'tools/util/perltidy.conf';
> -
> -my %policies;
> -my ( $list_policies_flag, $list_files_flag, @input_policies );
> -my $policy_group = 'default';
> -
> +my $theme = 'parrot';
>  GetOptions(
> -    'list'      => \$list_policies_flag,
> -    'listfiles' => \$list_files_flag,
> -    'policy=s'  => [EMAIL PROTECTED],
> -    'group=s'   => \$policy_group,         # all, default, extra
> +    'theme=s'   => \$theme
>  );
>
> -# if we we're given a policy (or policies), set it to the policies hash
> -# this still doesn't implement passing options to policies though...
> -# i.e. need to be able to handle --policy=foo=>{'bar'=>baz}
> -if (@input_policies) {
> -    foreach my $input_policy (@input_policies) {
> +my $config = File::Spec->catfile( qw{tools util perlcritic.conf} );
>
> -        # now split on commas if that's been used as well
> -        my @sub_policies = split( /,/, $input_policy );
> -        foreach my $sub_policy (@sub_policies) {
> -            $policies{$sub_policy} = 1;
> -        }
> -    }
> -}
> +Test::Perl::Critic->import(
> +    -profile => $config,
> +    -theme   => $theme
> +);
>
> -# get the files to check
> -my $DIST = Parrot::Distribution->new();
> +my $dist = Parrot::Distribution->new();
> +my $languages_dir = File::Spec->catdir( $PConfig{build_dir}, 'languages' );
> +
>  my @files;
>  if ( [EMAIL PROTECTED] ) {
>
> -    @files = map { $_->path } $DIST->get_perl_language_files();
> +    # Skip any files in languages/
> +    @files = grep { ! m{^\Q$languages_dir\E} }
> +             map { $_->path }
> +             $dist->get_perl_language_files();
>
> -    # Skip any language files...
> -    my $languages_dir = File::Spec->catdir( $PConfig{build_dir}, 'languages' 
> );
> -    @files = grep { !m{\Q$languages_dir\E} } @files;
> +} else {
> +    @files = @ARGV;
>  }
> -else {
>
> -    # if we're passed a directory, find all the matching files
> -    # under that directory.
> +plan(tests => scalar(@files));
> +critic_ok($_) foreach @files;
>
> -    # use $_ for the check below, as File::Find chdirs on us.
> -    # RT#44441 Change this to simply return all files in the distribution
> -    #     from this point down? -Coke
> -    foreach my $file (@ARGV) {
> -        ( -d $file )
> -            ? find(
> -            sub {
> -                if ( -d $_ and $_ eq '.svn' ) {
> -                    $File::Find::prune = 1;
> -                    return;
> -                }
> -                if ( is_perl($_) ) {
> -                    push @files, $File::Find::name;
> -                }
> -            },
> -            $file
> -            )
> -            : push @files, $file;
> -    }
> -}
> -
> -if ($list_files_flag) {
> -    print "Files to be tested by perlcritic:\n";
> -    for my $file (@files) {
> -        print $file, "\n";
> -    }
> -
> -    exit;
> -}
> -
> -# Add in the few cases we should care about.
> -# For a list of available policies, perldoc Perl::Critic
> -if ( keys %policies ) {
> -
> -    # if the policy is passed in on the command line, and it's one of the
> -    # ones where we require certain config arguments, then set them to the
> -    # ones we want here.
> -
> -    # XXX this information is being duplicated, we should only specify the
> -    # perltidyrc once, e.g.
> -
> -    if ( grep /CodeLayout::RequireTidyCode/, @input_policies ) {
> -        $policies{'CodeLayout::RequireTidyCode'} = { perltidyrc => 
> $perl_tidy_conf };
> -    }
> -    elsif ( grep /CodeLayout::ProhibitHardTabs/, @input_policies ) {
> -        $policies{'CodeLayout::ProhibitHardTabs'} = { allow_leading_tabs => 
> 0 };
> -    }
> -}
> -else {
> -    # otherwise, just run perlcritic.t normally
> -
> -    my %default_policies = (
> -        'BuiltinFunctions::ProhibitStringySplit'          => 1,
> -        'CodeLayout::ProhibitDuplicateCoda'               => 1,
> -        'CodeLayout::ProhibitHardTabs'                    => { 
> allow_leading_tabs => 0 },
> -        'CodeLayout::ProhibitTrailingWhitespace'          => 1,
> -        'CodeLayout::UseParrotCoda'                       => 1,
> -        'InputOutput::ProhibitBarewordFileHandles'        => 1,
> -        'InputOutput::ProhibitTwoArgOpen'                 => 1,
> -        'Subroutines::ProhibitExplicitReturnUndef'        => 1,
> -        'Subroutines::ProhibitSubroutinePrototypes'       => 1,
> -        'TestingAndDebugging::MisplacedShebang'           => 1,
> -        'TestingAndDebugging::ProhibitShebangWarningsArg' => 1,
> -        'TestingAndDebugging::RequirePortableShebang'     => 1,
> -        'TestingAndDebugging::RequireUseStrict'           => 1,
> -        'TestingAndDebugging::RequireUseWarnings'         => 1,
> -        'Variables::ProhibitConditionalDeclarations'      => 1,
> -    );
> -
> -    # Allow some names normally proscribed by PBP.
> -    my @ambiguousNames = grep {$_ ne 'abstract'}
> -        
> Perl::Critic::Policy::NamingConventions::ProhibitAmbiguousNames::default_forbidden_words();
> -
> -    # These policies are not yet passing consistently.
> -    my %extra_policies = (
> -        'CodeLayout::RequireTidyCode' =>
> -            { perltidyrc => $perl_tidy_conf },
> -        'NamingConventions::ProhibitAmbiguousNames' =>
> -            { forbid => join(" ", @ambiguousNames)},
> -        'Subroutines::ProhibitBuiltinHomonyms'      => 1,
> -        'Subroutines::RequireFinalReturn'           => 1,
> -    );
> -
> -    # Add Perl::Critic::Bangs if it exists
> -    eval { require Perl::Critic::Bangs; };
> -    if ($@) {
> -        diag "Perl::Critic::Bangs not installed: not testing for TODO items 
> in code";
> -    }
> -    else {
> -        $default_policies{'Bangs::ProhibitFlagComments'} = 1;
> -    }
> -
> -    # decide which policy group to use
> -    if ( $policy_group eq 'default' ) {
> -        %policies = %default_policies;
> -    }
> -    elsif ( $policy_group eq 'extra' ) {
> -        %policies = %extra_policies;
> -    }
> -    elsif ( $policy_group eq 'all' ) {
> -        %policies = ( %default_policies, %extra_policies );
> -    }
> -    else {
> -        warn "Unknown policy group, using 'default' policy group";
> -    }
> -
> -    # Give a diag to let users know if this is doing anything, how to repeat.
> -    if (exists $policies{'CodeLayout::RequireTidyCode'}) {
> -        eval { require Perl::Tidy; };
> -        if ( !$@ ) {
> -            diag "Using $perl_tidy_conf for Perl::Tidy settings";
> -        }
> -    }
> -}
> -
> -if ($list_policies_flag) {
> -    use Data::Dumper;
> -    $Data::Dumper::Indent = 1;
> -    $Data::Dumper::Terse  = 1;
> -    foreach my $policy ( sort keys %policies ) {
> -        if ( $policies{$policy} == 1 ) {
> -            print $policy, "\n";
> -        }
> -        else {
> -            warn $policy, " => ", Dumper( \$policies{$policy} );
> -        }
> -    }
> -    exit;
> -}
> -
> -# the number of tests is the number of policies
> -if ( keys %policies ) {
> -    plan tests => scalar keys %policies;
> -}
> -else {
> -    exit;
> -}
> -
> -# Create a critic object with all of the policies we care about.
> -
> -# By default, don't complain about anything.
> -my $config = Perl::Critic::Config->new( -exclude => [qr/.*/] );
> -
> -foreach my $policy ( keys %policies ) {
> -    $config->add_policy(
> -        -policy => $policy,
> -        ref $policies{$policy} ? ( -config => $policies{$policy} ) : (),
> -    ) or die;
> -}
> -
> -my $critic = Perl::Critic->new(
> -    -config => $config,
> -    -top    => 50,
> -);
> -
> -$Perl::Critic::Violation::FORMAT = '%f:%l.%c';
> -
> -my %violations = map { $_, [] } ( keys %policies );
> -
> -# check each file for the given policies
> -foreach my $file ( sort @files ) {
> -    if ( !-r $file ) {
> -        diag "skipping invalid file: $file\n";
> -        next;
> -    }
> -
> -    foreach my $violation ( $critic->critique($file) ) {
> -        my $policy = $violation->policy();
> -        $policy =~ s/^Perl::Critic::Policy:://;
> -        push @{ $violations{$policy} }, $violation->to_string();
> -    }
> -}
> -
> -foreach my $policy ( sort keys %violations ) {
> -    my @violations = @{ $violations{$policy} };
> -    ok( [EMAIL PROTECTED], $policy )
> -        or diag( "Policy: $policy failed in "
> -            . scalar @violations
> -            . " instances:\n"
> -            . join( "\n", @violations ) );
> -}
> -
>  __END__
>
>  =head1 NAME
> @@ -261,54 +59,25 @@
>
>  % prove t/codingstd/perlcritic.t
>
> - % perl --policy=TestingAndDebugging::RequireUseWarnings 
> t/codingstd/perlcritic.t
> + % perl --theme=extra t/codingstd/perlcritic.t
>
> - % perl --group=all t/codingstd/perlcritic.t
> + % perl t/codingstd/perlcritic.t <file>
>
> - % perl --group=extra t/codingstd/perlcritic.t
> -
>  =head1 DESCRIPTION
>
>  Tests all perl source files for some very specific perl coding violations.
>
>  Optionally specify directories or files on the command line to test B<only>
> -those files, otherwise all files in the C<MANIFEST> will be checked.
> +those files, otherwise all perl 5 files in the C<MANIFEST> will be checked.
>
> -By default, this script will validate the specified files against a default
> -set of policies. To run the test for a B<specific> Rule, specify it on the
> -command line before any other files, as:
> +This test uses a standard perlcriticrc file, located in
> +F<tools/utils/perlcritic.conf>
>
> - perl t/codingstd/perlcritic.t 
> --policy=TestingAndDebugging::RequireUseWarnings
> +If you wish to run a specific policy, the easiest way to do so is to 
> temporarily add
> +a custom theme to the configuration file and then specify that on the command
> +line to this script.
>
> -This will, for example, use B<only> that policy (see L<Perl::Critic> for
> -more information on policies) when examining files from the manifest.
> -
> -Multiple policies can be specified either by separating the individual
> -policies with a comma:
> -
> - --policy=foo,bar
> -
> -and/or by specifying the C<--policy> argument multiple times on the command
> -line.
> -
> -If you just wish to get a listing of the polices that will be checked
> -without actually running them, use:
> -
> - perl t/codingstd/perlcritic.t --list
> -
> -If you just wish to get a listing of the files that will be checked
> -without actually running the tests, use:
> -
> - perl t/codingstd/perlcritic.t --listfiles
> -
> -Not all policies are analysed by default.  To process the extra policies,
> -use the C<--group=extra> argument.  To process all policies use:
> -
> - perl t/codingstd/perlcritic.t --group=all
> -
> -=head1 BUGS AND LIMITATIONS
> -
> -There's no way to specify options to policies when they are specified on the
> +If you wish to test a specific file, you can pass that as an argument on the
>  command line.
>
>  =cut
>
>



-- 
Will "Coke" Coleda

Reply via email to