File Coverage

blib/lib/criticism.pm
Criterion Covered Total %
statement 46 49 93.8
branch 8 12 66.6
condition 9 15 60.0
subroutine 8 8 100.0
pod n/a
total 71 84 84.5


line stmt bran cond sub pod time code
1             #######################################################################
2             # $URL: http://perlcritic.tigris.org/svn/perlcritic/tags/criticism-1.02/lib/criticism.pm $
3             # $Date: 2008-07-27 16:11:59 -0700 (Sun, 27 Jul 2008) $
4             # $Author: thaljef $
5             # $Revision: 203 $
6             ########################################################################
7              
8             package criticism;
9              
10 3     3   3319 use strict;
  3         6  
  3         124  
11 3     3   16 use warnings;
  3         6  
  3         210  
12 3     3   2295 use English qw(-no_match_vars);
  3         5222  
  3         25  
13 3     3   1550 use Carp qw(carp croak);
  3         6  
  3         2298  
14              
15             #-----------------------------------------------------------------------------
16              
17             our $VERSION = 1.02;
18              
19             #-----------------------------------------------------------------------------
20             # We could use the SEVERITY constants from Perl::Critic instead of magic
21             # numbers. That would require us to load Perl::Critic, but this pragma
22             # must fail gracefully if Perl::Critic is not available. Therefore, we're
23             # going to tolerate the magic numbers.
24              
25             ## no critic (ProhibitMagicNumbers);
26             my %SEVERITY_OF = (
27             gentle => 5,
28             stern => 4,
29             harsh => 3,
30             cruel => 2,
31             brutal => 1,
32             );
33             ## use critic;
34              
35             my $DEFAULT_MOOD = 'gentle';
36             my $DEFAULT_VERBOSE = "%m at %f line %l.\n";
37              
38             #-----------------------------------------------------------------------------
39              
40             sub import {
41              
42 9     9   8117 my ($pkg, @args) = @_;
43 9         35 my $file = (caller)[1];
44 9 50       309 return 1 if not -f $file;
45 9         38 my %pc_args = _make_pc_args( @args );
46 8         30 return _critique( $file, %pc_args );
47             }
48              
49             #-----------------------------------------------------------------------------
50              
51             sub _make_pc_args {
52              
53 18     18   7916 my (@args) = @_;
54 18         40 my %pc_args = ();
55              
56 18 100       58 if (@args <= 1 ) {
57 13   66     54 my $mood = $args[0] || $DEFAULT_MOOD;
58 13   66     51 my $severity = $SEVERITY_OF{$mood} || _throw_mood_exception( $mood );
59 12         56 %pc_args = (-severity => $severity, -verbose => $DEFAULT_VERBOSE);
60             }
61             else {
62 5         14 %pc_args = @args;
63 5   66     40 $pc_args{-verbose} ||= $DEFAULT_VERBOSE;
64             }
65              
66 17         93 return %pc_args;
67             }
68              
69             #-----------------------------------------------------------------------------
70              
71             sub _critique {
72              
73 8     8   31 my ($file, %pc_args) = @_;
74 8         17 my @violations = ();
75 8         17 my $critic = undef;
76              
77             eval {
78 8         4266 require Perl::Critic;
79 8         4544005 require Perl::Critic::Violation;
80 8         75 $critic = Perl::Critic->new( %pc_args );
81 8         5023267 my $verbose = $critic->config->verbose();
82 8         131 Perl::Critic::Violation::set_format($verbose);
83 8         1439 @violations = $critic->critique($file);
84 8         683463 print {*STDERR} @violations;
  8         102  
85 8         6261 1;
86             }
87 8 50       12 or do {
88 0 0 0     0 if ($ENV{DEBUG} || $PERLDB) {
89 0         0 carp qq{'criticism' failed to load: $EVAL_ERROR};
90 0         0 return;
91             }
92             };
93              
94 8 100 100     74 die "Refusing to continue due to Perl::Critic violations.\n"
95             if @violations && $critic->config->criticism_fatal();
96              
97 7 100       5214 return @violations ? 0 : 1;
98             }
99              
100             #-----------------------------------------------------------------------------
101              
102             sub _throw_mood_exception {
103 1     1   2 my ($mood) = @_;
104 1         7 my @moods = keys %SEVERITY_OF;
105 1         6 @moods = reverse sort { $SEVERITY_OF{$a} <=> $SEVERITY_OF{$b} } @moods;
  5         11  
106 1         224 croak qq{"$mood" criticism not supported. Choose from: @moods};
107             }
108              
109             1;
110              
111             __END__
112              
113             #-----------------------------------------------------------------------------
114              
115             =pod
116              
117             =for stopwords API Thalhammer perlcritic pragma pseudo-pragma
118              
119             =head1 NAME
120              
121             criticism - Perl pragma to enforce coding standards and best-practices
122              
123             =head1 SYNOPSIS
124              
125             use criticism;
126              
127             use criticism 'gentle';
128             use criticism 'stern';
129             use criticism 'harsh';
130             use criticism 'cruel';
131             use criticism 'brutal';
132              
133             use criticism ( -profile => '/foo/bar/perlcriticrc' );
134             use criticism ( -severity => 3, -verbose => '%m at %f line %l' );
135              
136             =head1 DESCRIPTION
137              
138             This pragma enforces coding standards and promotes best-practices by
139             running your file through L<Perl::Critic|Perl::Critic> before every
140             execution. In a production system, this usually isn't feasible
141             because it adds a lot of overhead at start-up. If you have a separate
142             development environment, you can effectively bypass the C<criticism>
143             pragma by not installing L<Perl::Critic|Perl::Critic> in the
144             production environment. If L<Perl::Critic|Perl::Critic> can't be
145             loaded, then C<criticism> just fails silently.
146              
147             Alternatively, the C<perlcritic> command-line (which is distributed
148             with L<Perl::Critic|Perl::Critic>) can be used to analyze your files
149             on-demand and has some additional configuration features. And
150             L<Test::Perl::Critic|Test::Perl::Critic> provides a nice interface for
151             analyzing files during the build process.
152              
153             If you'd like to try L<Perl::Critic|Perl::Critic> without installing
154             anything, there is a web-service available at
155             L<http://perlcritic.com>. The web-service does not yet support all
156             the configuration features that are available in the native
157             Perl::Critic API, but it should give you a good idea of what it does.
158             You can also invoke the perlcritic web-service from the command line
159             by doing an HTTP-post, such as one of these:
160              
161             $> POST http://perlcritic.com/perl/critic.pl < MyModule.pm
162             $> lwp-request -m POST http://perlcritic.com/perl/critic.pl < MyModule.pm
163             $> wget -q -O - --post-file=MyModule.pm http://perlcritic.com/perl/critic.pl
164              
165             Please note that the perlcritic web-service is still alpha code. The
166             URL and interface to the service are subject to change.
167              
168             =head1 CONFIGURATION
169              
170             If there is B<exactly one> import argument, then it is taken to be a
171             named equivalent to one of the numeric severity levels supported by
172             L<Perl::Critic|Perl::Critic>. For example, C<use criticism 'gentle';>
173             is equivalent to setting the C<< -severity => 5 >>, which reports only
174             the most dangerous violations. On the other hand, C<use criticism
175             'brutal';> is like setting the C<< -severity => 1 >>, which reports
176             B<every> violation. If there are no import arguments, then it
177             defaults to C<'gentle'>.
178              
179             If there is more than one import argument, then they will all be
180             passed directly into the L<Perl::Critic|Perl::Critic> constructor. So you can use
181             whatever arguments are supported by Perl::Critic.
182              
183             The C<criticism> pragma will also obey whatever configurations you
184             have set in your F<.perlcriticrc> file. In particular, setting the
185             C<criticism-fatal> option to a true value will cause your program to
186             immediately C<die> if any Perl::Critic violations are found.
187             Otherwise, violations are merely advisory. This option can be set in
188             the global section at the top of your F<.perlcriticrc> file, like
189             this:
190              
191             # Top of your .perlcriticrc file...
192             criticism-fatal = 1
193              
194             # per-policy configurations follow...
195              
196             You can also pass C<< ('-criticism-fatal' => 1) >> as import
197             arguments, just like any other L<Perl::Critic|Perl::Critic> argument.
198             See L<Perl::Critic/"CONFIGURATION"> for details on the other
199             configuration options.
200              
201             =head1 DIAGNOSTICS
202              
203             Usually, the C<criticism> pragma fails silently if it cannot load
204             Perl::Critic. So by B<not> installing Perl::Critic in your production
205             environment, you can leave the C<criticism> pragma in your production
206             source code and it will still compile, but it won't be analyzed by
207             Perl::Critic each time it runs.
208              
209             However, if you set the C<DEBUG> environment variable to a true value
210             or run your program under the Perl debugger, you will get a warning
211             when C<criticism> fails to load L<Perl::Critic|Perl::Critic>.
212              
213             =head1 NOTES
214              
215             The C<criticism> pragma applies to the entire file, so it is not
216             affected by scope or package boundaries and C<use>-ing it multiple
217             times will just cause it to repeatedly process the same file. There
218             isn't a reciprocal C<no criticism> pragma. However,
219             L<Perl::Critic|Perl::Critic> does support a pseudo-pragma that directs
220             it to overlook certain lines or blocks of code. See
221             L<Perl::Critic/"BENDING THE RULES"> for more details.
222              
223             =head1 AUTHOR
224              
225             Jeffrey Ryan Thalhammer <thaljef@cpan.org>
226              
227             =head1 COPYRIGHT
228              
229             Copyright (c) 2006-2007 Jeffrey Ryan Thalhammer. All rights reserved.
230              
231             This program is free software; you can redistribute it and/or modify
232             it under the same terms as Perl itself. The full text of this license
233             can be found in the LICENSE file included with this module.
234              
235             =cut