File Coverage

blib/lib/Perl/Critic/Command.pm
Criterion Covered Total %
statement 90 289 31.1
branch 27 112 24.1
condition 25 59 42.3
subroutine 20 39 51.2
pod 1 1 100.0
total 163 500 32.6


line stmt bran cond sub pod time code
1             package Perl::Critic::Command;
2              
3 3     3   9415 use 5.010001;
  3         22  
4 3     3   16 use strict;
  3         9  
  3         78  
5 3     3   14 use warnings;
  3         6  
  3         105  
6              
7 3     3   17 use English qw< -no_match_vars >;
  3         9  
  3         22  
8 3     3   1849 use Readonly;
  3         4720  
  3         206  
9              
10 3     3   786 use Getopt::Long qw< GetOptions >;
  3         13040  
  3         32  
11 3     3   501 use List::Util qw< first max >;
  3         7  
  3         270  
12 3     3   1873 use Pod::Usage qw< pod2usage >;
  3         69271  
  3         257  
13              
14 3     3   553 use Perl::Critic::Exception::Parse ();
  3         11  
  3         90  
15 3         201 use Perl::Critic::Utils qw<
16             :characters :severities policy_short_name
17             $DEFAULT_VERBOSITY $DEFAULT_VERBOSITY_WITH_FILE_NAME
18 3     3   29 >;
  3         10  
19 3     3   1627 use Perl::Critic::Utils::Constants qw< $_MODULE_VERSION_TERM_ANSICOLOR >;
  3         9  
  3         279  
20 3     3   500 use Perl::Critic::Violation qw<>;
  3         10  
  3         117  
21              
22             #-----------------------------------------------------------------------------
23              
24             our $VERSION = '1.146';
25              
26             #-----------------------------------------------------------------------------
27              
28 3     3   16 use Exporter 'import';
  3         7  
  3         11792  
29              
30             Readonly::Array our @EXPORT_OK => qw< run >;
31              
32             Readonly::Hash our %EXPORT_TAGS => (
33             all => [ @EXPORT_OK ],
34             );
35              
36             #-----------------------------------------------------------------------------
37              
38             Readonly::Scalar my $DEFAULT_VIOLATIONS_FOR_TOP => 20;
39              
40             Readonly::Scalar my $EXIT_SUCCESS => 0;
41             Readonly::Scalar my $EXIT_NO_FILES => 1;
42             Readonly::Scalar my $EXIT_HAD_VIOLATIONS => 2;
43             Readonly::Scalar my $EXIT_HAD_FILE_PROBLEMS => 3;
44              
45             #-----------------------------------------------------------------------------
46              
47             my @files = ();
48             my $critic = undef;
49             my $output = \*STDOUT;
50              
51             #-----------------------------------------------------------------------------
52              
53             sub _out {
54 0     0   0 my @lines = @_;
55 0         0 return print {$output} @lines;
  0         0  
56             }
57              
58             #-----------------------------------------------------------------------------
59              
60             sub run {
61 0     0 1 0 my %options = _get_options();
62 0         0 @files = _get_input(@ARGV);
63              
64 0         0 my ($violations, $had_error_in_file) = _critique(\%options, @files);
65              
66 0 0       0 return $EXIT_HAD_FILE_PROBLEMS if $had_error_in_file;
67 0 0       0 return $EXIT_NO_FILES if not defined $violations;
68 0 0       0 return $EXIT_HAD_VIOLATIONS if $violations;
69              
70 0         0 return $EXIT_SUCCESS;
71             }
72              
73             #-----------------------------------------------------------------------------
74              
75             sub _get_options {
76              
77 52     52   35201 my %opts = _parse_command_line();
78 52         182 _dispatch_special_requests( %opts );
79 49         143 _validate_options( %opts );
80              
81             # Convert severity shortcut options. If multiple shortcuts
82             # are given, the lowest one wins. If an explicit --severity
83             # option has been given, then the shortcuts are ignored. The
84             # @SEVERITY_NAMES variable is exported by Perl::Critic::Utils.
85 44   100 172   369 $opts{-severity} ||= first { exists $opts{"-$_"} } @SEVERITY_NAMES;
  172         1274  
86 44   100 162   325 $opts{-severity} ||= first { exists $opts{"-$_"} } ($SEVERITY_LOWEST .. $SEVERITY_HIGHEST);
  162         310  
87              
88              
89             # If --top is specified, default the severity level to 1, unless an
90             # explicit severity is defined. This provides us flexibility to
91             # report top-offenders across just some or all of the severity levels.
92             # We also default the --top count to twenty if none is given
93 44 100       172 if ( exists $opts{-top} ) {
94 5   100     20 $opts{-severity} ||= 1;
95 5   66     15 $opts{-top} ||= $DEFAULT_VIOLATIONS_FOR_TOP;
96             }
97              
98             #Override profile, if --noprofile is specified
99 44 100       99 if ( exists $opts{-noprofile} ) {
100 1         5 $opts{-profile} = $EMPTY;
101             }
102              
103 44         238 return %opts;
104             }
105              
106             #-----------------------------------------------------------------------------
107              
108             sub _parse_command_line {
109 52     52   94 my %opts;
110 52         126 my @opt_specs = _get_option_specification();
111 52         194 Getopt::Long::Configure('no_ignore_case');
112 52 50       1819 GetOptions( \%opts, @opt_specs ) || pod2usage(); #Exits
113              
114             # I've adopted the convention of using key-value pairs for
115             # arguments to most functions. And to increase legibility,
116             # I have also adopted the familiar command-line practice
117             # of denoting argument names with a leading dash (-).
118 52         143116 my %dashed_opts = map { ( "-$_" => $opts{$_} ) } keys %opts;
  75         330  
119 52         289 return %dashed_opts;
120             }
121              
122             #-----------------------------------------------------------------------------
123              
124             sub _dispatch_special_requests {
125 52     52   122 my (%opts) = @_;
126 52 100       137 if ( $opts{-help} ) { pod2usage( -verbose => 0 ) } # Exits
  1         11  
127 51 100       111 if ( $opts{-options} ) { pod2usage( -verbose => 1 ) } # Exits
  1         10  
128 50 100       100 if ( $opts{-man} ) { pod2usage( -verbose => 2 ) } # Exits
  1         5  
129 49 50       99 if ( $opts{-version} ) { _display_version() } # Exits
  0         0  
130 49 50       94 if ( $opts{-list} ) { _render_all_policy_listing() } # Exits
  0         0  
131 49 50       96 if ( $opts{'-list-enabled'} ) { _render_policy_listing(%opts) } # Exits
  0         0  
132 49 50       98 if ( $opts{'-list-themes'} ) { _render_theme_listing() } # Exits
  0         0  
133 49 50       112 if ( $opts{'-profile-proto'} ) { _render_profile_prototype() } # Exits
  0         0  
134 49 50       106 if ( $opts{-doc} ) { _render_policy_docs( %opts ) } # Exits
  0         0  
135 49         94 return 1;
136             }
137              
138             #-----------------------------------------------------------------------------
139              
140             sub _validate_options {
141 49     49   95 my (%opts) = @_;
142 49         90 my $msg = $EMPTY;
143              
144              
145 49 100 100     116 if ( $opts{-noprofile} && $opts{-profile} ) {
146 1         5 $msg .= qq{Warning: Cannot use -noprofile with -profile option.\n};
147             }
148              
149 49 100 100     141 if ( $opts{-verbose} && $opts{-verbose} !~ m{(?: \d+ | %[mfFlcCedrpPs] )}xms) {
150 1         7 $msg .= qq<Warning: --verbose arg "$opts{-verbose}" looks odd. >;
151 1         5 $msg .= qq<Perhaps you meant to say "--verbose 3 $opts{-verbose}."\n>;
152             }
153              
154 49 100 100     133 if ( exists $opts{-top} && $opts{-top} < 0 ) {
155 1         5 $msg .= qq<Warning: --top argument "$opts{-top}" is negative. >;
156 1         3 $msg .= qq<Perhaps you meant to say "$opts{-top} --top".\n>;
157             }
158              
159 49 100 100     141 if (
      100        
160             exists $opts{-severity}
161             && (
162             $opts{-severity} < $SEVERITY_LOWEST
163             || $opts{-severity} > $SEVERITY_HIGHEST
164             )
165             ) {
166 2         10 $msg .= qq<Warning: --severity arg "$opts{-severity}" out of range. >;
167 2         7 $msg .= qq<Severities range from "$SEVERITY_LOWEST" (lowest) to >;
168 2         5 $msg .= qq<"$SEVERITY_HIGHEST" (highest).\n>;
169             }
170              
171              
172 49 100       96 if ( $msg ) {
173 5         25 pod2usage( -exitstatus => 1, -message => $msg, -verbose => 0); #Exits
174             }
175              
176              
177 44         86 return 1;
178             }
179              
180             #-----------------------------------------------------------------------------
181              
182             sub _get_input {
183              
184 0     0   0 my @args = @_;
185              
186 0 0 0     0 if ( !@args || (@args == 1 && $args[0] eq q{-}) ) {
      0        
187              
188             # Reading code from STDIN. All the code is slurped into
189             # a string. PPI will barf if the string is just whitespace.
190 0         0 my $code_string = do { local $RS = undef; <> };
  0         0  
  0         0  
191              
192             # Notice if STDIN was closed (pipe error, etc)
193 0   0     0 $code_string //= $EMPTY;
194              
195 0 0       0 $code_string =~ m{ \S+ }xms || die qq{Nothing to critique.\n};
196 0         0 return \$code_string; #Convert to SCALAR ref for PPI
197             }
198             else {
199              
200             # Test to make sure all the specified files or directories
201             # actually exist. If any one of them is bogus, then die.
202 0 0   0   0 if ( my $nonexistent = first { ! -e } @args ) {
  0         0  
203 0         0 my $msg = qq{No such file or directory: '$nonexistent'};
204 0         0 pod2usage( -exitstatus => 1, -message => $msg, -verbose => 0);
205             }
206              
207             # Reading code from files or dirs. If argument is a file,
208             # then we process it as-is (even though it may not actually
209             # be Perl code). If argument is a directory, recursively
210             # search the directory for files that look like Perl code.
211 0 0       0 return map { (-d) ? Perl::Critic::Utils::all_perl_files($_) : $_ } @args;
  0         0  
212             }
213             }
214              
215             #------------------------------------------------------------------------------
216              
217             sub _critique {
218              
219 0     0   0 my ( $opts_ref, @files_to_critique ) = @_;
220 0 0       0 @files_to_critique || die "No perl files were found.\n";
221              
222             # Perl::Critic has lots of dependencies, so loading is delayed
223             # until it is really needed. This hack reduces startup time for
224             # doing other things like getting the version number or dumping
225             # the man page. Arguably, those things are pretty rare, but hey,
226             # why not save a few seconds if you can.
227              
228 0         0 require Perl::Critic;
229 0         0 $critic = Perl::Critic->new( %{$opts_ref} );
  0         0  
230 0 0       0 $critic->policies() || die "No policies selected.\n";
231              
232 0         0 _set_up_pager($critic->config()->pager());
233              
234 0         0 my $number_of_violations = undef;
235 0         0 my $had_error_in_file = 0;
236              
237 0         0 for my $file (@files_to_critique) {
238              
239             eval {
240 0         0 my @violations = $critic->critique($file);
241 0         0 $number_of_violations += scalar @violations;
242              
243 0 0       0 if (not $opts_ref->{'-statistics-only'}) {
244 0         0 _render_report( $file, $opts_ref, @violations )
245             }
246 0         0 1;
247             }
248 0 0       0 or do {
249 0 0       0 if ( my $exception = Perl::Critic::Exception::Parse->caught() ) {
    0          
250 0         0 $had_error_in_file = 1;
251 0         0 warn qq<Problem while critiquing "$file": $EVAL_ERROR\n>;
252             }
253             elsif ($EVAL_ERROR) {
254             # P::C::Exception::Fatal includes the stack trace in its
255             # stringification.
256 0         0 die qq<Fatal error while critiquing "$file": $EVAL_ERROR\n>;
257             }
258             else {
259 0         0 die qq<Fatal error while critiquing "$file". Unfortunately, >,
260             q<$@/$EVAL_ERROR >, ## no critic (RequireInterpolationOfMetachars)
261             qq<is empty, so the reason can't be shown.\n>;
262             }
263             }
264             }
265              
266 0 0 0     0 if ( $opts_ref->{-statistics} or $opts_ref->{'-statistics-only'} ) {
267 0         0 my $stats = $critic->statistics();
268 0         0 _report_statistics( $opts_ref, $stats );
269             }
270              
271 0         0 return $number_of_violations, $had_error_in_file;
272             }
273              
274             #------------------------------------------------------------------------------
275              
276             sub _render_report {
277 0     0   0 my ( $file, $opts_ref, @violations ) = @_;
278              
279             # Only report the files, if asked.
280 0         0 my $number_of_violations = scalar @violations;
281 0 0 0     0 if ( $opts_ref->{'-files-with-violations'} ||
282             $opts_ref->{'-files-without-violations'} ) {
283             not ref $file
284 0 0 0     0 and $opts_ref->{$number_of_violations ? '-files-with-violations' :
    0          
285             '-files-without-violations'}
286             and _out "$file\n";
287 0         0 return $number_of_violations;
288             }
289              
290             # Only report the number of violations, if asked.
291 0 0       0 if( $opts_ref->{-count} ){
292 0 0       0 ref $file || _out "$file: ";
293 0         0 _out "$number_of_violations\n";
294 0         0 return $number_of_violations;
295             }
296              
297             # Hail all-clear unless we should shut up.
298 0 0 0     0 if( !@violations && !$opts_ref->{-quiet} ) {
299 0 0       0 ref $file || _out "$file ";
300 0         0 _out "source OK\n";
301 0         0 return 0;
302             }
303              
304             # Otherwise, format and print violations
305 0         0 my $verbosity = $critic->config->verbose();
306             # $verbosity can be numeric or string, so use "eq" for comparison;
307 0 0 0     0 $verbosity =
308             ($verbosity eq $DEFAULT_VERBOSITY && @files > 1)
309             ? $DEFAULT_VERBOSITY_WITH_FILE_NAME
310             : $verbosity;
311 0         0 my $fmt = Perl::Critic::Utils::verbosity_to_format( $verbosity );
312 0 0       0 if (not -f $file) { $fmt =~ s< \%[fF] ><STDIN>xms; } #HACK!
  0         0  
313 0         0 Perl::Critic::Violation::set_format( $fmt );
314              
315 0         0 my $color = $critic->config->color();
316 0 0       0 _out $color ? _colorize_by_severity(@violations) : @violations;
317              
318 0         0 return $number_of_violations;
319             }
320              
321             #-----------------------------------------------------------------------------
322              
323             sub _set_up_pager {
324 0     0   0 my ($pager_command) = @_;
325 0 0       0 return if not $pager_command;
326 0 0       0 return if not _at_tty();
327              
328 0 0       0 open my $pager, q<|->, $pager_command ## no critic (InputOutput::RequireBriefOpen)
329             or die qq<Unable to pipe to pager "$pager_command": $ERRNO\n>;
330              
331 0         0 $output = $pager;
332              
333 0         0 return;
334             }
335              
336             #-----------------------------------------------------------------------------
337              
338             sub _report_statistics {
339 0     0   0 my ($opts_ref, $statistics) = @_;
340              
341 0 0 0     0 if (
      0        
342             not $opts_ref->{'-statistics-only'}
343             and (
344             $statistics->total_violations()
345             or not $opts_ref->{-quiet} and $statistics->modules()
346             )
347             ) {
348 0         0 _out "\n"; # There's prior output that we want to separate from.
349             }
350              
351 0         0 my $files = _commaify($statistics->modules());
352 0         0 my $subroutines = _commaify($statistics->subs());
353 0         0 my $statements = _commaify($statistics->statements_other_than_subs());
354 0         0 my $lines = _commaify($statistics->lines());
355 0         0 my $width = max map { length } $files, $subroutines, $statements;
  0         0  
356              
357 0         0 _out sprintf "%*s %s.\n", $width, $files, 'files';
358 0         0 _out sprintf "%*s %s.\n", $width, $subroutines, 'subroutines/methods';
359 0         0 _out sprintf "%*s %s.\n", $width, $statements, 'statements';
360              
361 0         0 my $lines_of_blank = _commaify( $statistics->lines_of_blank() );
362 0         0 my $lines_of_comment = _commaify( $statistics->lines_of_comment() );
363 0         0 my $lines_of_data = _commaify( $statistics->lines_of_data() );
364 0         0 my $lines_of_perl = _commaify( $statistics->lines_of_perl() );
365 0         0 my $lines_of_pod = _commaify( $statistics->lines_of_pod() );
366              
367             $width =
368 0         0 max map { length }
  0         0  
369             $lines_of_blank, $lines_of_comment, $lines_of_data,
370             $lines_of_perl, $lines_of_pod;
371 0         0 _out sprintf "\n%s %s:\n", $lines, 'lines, consisting of';
372 0         0 _out sprintf " %*s %s.\n", $width, $lines_of_blank, 'blank lines';
373 0         0 _out sprintf " %*s %s.\n", $width, $lines_of_comment, 'comment lines';
374 0         0 _out sprintf " %*s %s.\n", $width, $lines_of_data, 'data lines';
375 0         0 _out sprintf " %*s %s.\n", $width, $lines_of_perl, 'lines of Perl code';
376 0         0 _out sprintf " %*s %s.\n", $width, $lines_of_pod, 'lines of POD';
377              
378 0         0 my $average_sub_mccabe = $statistics->average_sub_mccabe();
379 0 0       0 if (defined $average_sub_mccabe) {
380 0         0 _out
381             sprintf
382             "\nAverage McCabe score of subroutines was %.2f.\n",
383             $average_sub_mccabe;
384             }
385              
386 0         0 _out "\n";
387              
388 0         0 _out _commaify($statistics->total_violations()), " violations.\n";
389              
390 0         0 my $violations_per_file = $statistics->violations_per_file();
391 0 0       0 if (defined $violations_per_file) {
392 0         0 _out
393             sprintf
394             "Violations per file was %.3f.\n",
395             $violations_per_file;
396             }
397 0         0 my $violations_per_statement = $statistics->violations_per_statement();
398 0 0       0 if (defined $violations_per_statement) {
399 0         0 _out
400             sprintf
401             "Violations per statement was %.3f.\n",
402             $violations_per_statement;
403             }
404 0         0 my $violations_per_line = $statistics->violations_per_line_of_code();
405 0 0       0 if (defined $violations_per_line) {
406 0         0 _out
407             sprintf
408             "Violations per line of code was %.3f.\n",
409             $violations_per_line;
410             }
411              
412 0 0       0 if ( $statistics->total_violations() ) {
413 0         0 _out "\n";
414              
415 0         0 my %severity_violations = %{ $statistics->violations_by_severity() };
  0         0  
416 0         0 my @severities = reverse sort keys %severity_violations;
417             $width =
418             max
419 0         0 map { length _commaify( $severity_violations{$_} ) }
  0         0  
420             @severities;
421 0         0 foreach my $severity (@severities) {
422             _out
423             sprintf
424             "%*s severity %d violations.\n",
425             $width,
426 0         0 _commaify( $severity_violations{$severity} ),
427             $severity;
428             }
429              
430 0         0 _out "\n";
431              
432 0         0 my %policy_violations = %{ $statistics->violations_by_policy() };
  0         0  
433 0         0 my @policies = sort keys %policy_violations;
434             $width =
435             max
436 0         0 map { length _commaify( $policy_violations{$_} ) }
  0         0  
437             @policies;
438 0         0 foreach my $policy (@policies) {
439             _out
440             sprintf
441             "%*s violations of %s.\n",
442             $width,
443 0         0 _commaify($policy_violations{$policy}),
444             policy_short_name($policy);
445             }
446             }
447              
448 0         0 return;
449             }
450              
451             #-----------------------------------------------------------------------------
452              
453             # Only works for integers.
454             sub _commaify {
455 0     0   0 my ( $number ) = @_;
456              
457 0         0 while ($number =~ s/ \A ( [-+]? \d+ ) ( \d{3} ) /$1,$2/xms) {
458             # nothing
459             }
460              
461 0         0 return $number;
462             }
463              
464             #-----------------------------------------------------------------------------
465              
466             sub _get_option_specification {
467              
468 52     52   330 return qw<
469             5 4 3 2 1
470             version
471             brutal
472             count|C
473             cruel
474             doc=s
475             exclude=s@
476             force!
477             gentle
478             harsh
479             help|?|H
480             include=s@
481             list
482             list-enabled
483             list-themes
484             man
485             color|colour!
486             noprofile
487             only!
488             options
489             pager=s
490             profile|p=s
491             profile-proto
492             quiet
493             severity=i
494             single-policy|s=s
495             stern
496             statistics!
497             statistics-only!
498             profile-strictness=s
499             theme=s
500             top:i
501             allow-unsafe
502             verbose=s
503             color-severity-highest|colour-severity-highest|color-severity-5|colour-severity-5=s
504             color-severity-high|colour-severity-high|color-severity-4|colour-severity-4=s
505             color-severity-medium|colour-severity-medium|color-severity-3|colour-severity-3=s
506             color-severity-low|colour-severity-low|color-severity-2|colour-severity-2=s
507             color-severity-lowest|colour-severity-lowest|color-severity-1|colour-severity-1=s
508             files-with-violations|l
509             files-without-violations|L
510             program-extensions=s@
511             >;
512             }
513              
514             #-----------------------------------------------------------------------------
515              
516             sub _colorize_by_severity {
517 0     0     my @violations = @_;
518 0 0 0       return @violations if _this_is_windows() && !eval 'require Win32::Console::ANSI; 1';
519 0 0         return @violations if not eval {
520 0           require Term::ANSIColor;
521 0           Term::ANSIColor->VERSION( $_MODULE_VERSION_TERM_ANSICOLOR );
522 0           1;
523             };
524              
525 0           my $config = $critic->config();
526 0           my %color_of = (
527             $SEVERITY_HIGHEST => $config->color_severity_highest(),
528             $SEVERITY_HIGH => $config->color_severity_high(),
529             $SEVERITY_MEDIUM => $config->color_severity_medium(),
530             $SEVERITY_LOW => $config->color_severity_low(),
531             $SEVERITY_LOWEST => $config->color_severity_lowest(),
532             );
533              
534 0           return map { _colorize( "$_", $color_of{$_->severity()} ) } @violations;
  0            
535              
536             }
537              
538             #-----------------------------------------------------------------------------
539              
540             sub _colorize {
541 0     0     my ($string, $color) = @_;
542 0 0         return $string if not defined $color;
543 0 0         return $string if $color eq $EMPTY;
544             # $terminator is a purely cosmetic change to make the color end at the end
545             # of the line rather than right before the next line. It is here because
546             # if you use background colors, some console windows display a little
547             # fragment of colored background before the next uncolored (or
548             # differently-colored) line.
549 0 0         my $terminator = chomp $string ? "\n" : $EMPTY;
550 0           return Term::ANSIColor::colored( $string, $color ) . $terminator;
551             }
552              
553             #-----------------------------------------------------------------------------
554              
555             sub _this_is_windows {
556 0 0   0     return 1 if $OSNAME =~ m/MSWin32/xms;
557 0           return 0;
558             }
559              
560             #-----------------------------------------------------------------------------
561              
562             sub _at_tty {
563 0     0     return -t STDOUT; ## no critic (ProhibitInteractiveTest);
564             }
565              
566             #-----------------------------------------------------------------------------
567              
568             sub _render_all_policy_listing {
569             # Force P-C parameters, to catch all Policies on this site
570 0     0     my %pc_params = (-profile => $EMPTY, -severity => $SEVERITY_LOWEST);
571 0           return _render_policy_listing( %pc_params );
572             }
573              
574             #-----------------------------------------------------------------------------
575              
576             sub _render_policy_listing {
577 0     0     my %pc_params = @_;
578              
579 0           require Perl::Critic::PolicyListing;
580 0           require Perl::Critic;
581              
582 0           my @policies = Perl::Critic->new( %pc_params )->policies();
583 0           my $listing = Perl::Critic::PolicyListing->new( -policies => \@policies );
584 0           _out $listing;
585              
586 0           exit $EXIT_SUCCESS;
587             }
588              
589             #-----------------------------------------------------------------------------
590              
591             sub _render_theme_listing {
592              
593 0     0     require Perl::Critic::ThemeListing;
594 0           require Perl::Critic;
595              
596 0           my %pc_params = (-profile => $EMPTY, -severity => $SEVERITY_LOWEST);
597 0           my @policies = Perl::Critic->new( %pc_params )->policies();
598 0           my $listing = Perl::Critic::ThemeListing->new( -policies => \@policies );
599 0           _out $listing;
600              
601 0           exit $EXIT_SUCCESS;
602             }
603              
604             #-----------------------------------------------------------------------------
605              
606             sub _render_profile_prototype {
607              
608 0     0     require Perl::Critic::ProfilePrototype;
609 0           require Perl::Critic;
610              
611 0           my %pc_params = (-profile => $EMPTY, -severity => $SEVERITY_LOWEST);
612 0           my @policies = Perl::Critic->new( %pc_params )->policies();
613 0           my $prototype = Perl::Critic::ProfilePrototype->new( -policies => \@policies );
614 0           _out $prototype;
615              
616 0           exit $EXIT_SUCCESS;
617             }
618              
619             #-----------------------------------------------------------------------------
620              
621             sub _render_policy_docs {
622              
623 0     0     my (%opts) = @_;
624 0           my $pattern = delete $opts{-doc};
625              
626 0           require Perl::Critic;
627 0           $critic = Perl::Critic->new(%opts);
628 0           _set_up_pager($critic->config()->pager());
629              
630 0           require Perl::Critic::PolicyFactory;
631 0           my @site_policies = Perl::Critic::PolicyFactory->site_policy_names();
632 0           my @matching_policies = grep { /$pattern/ixms } @site_policies;
  0            
633              
634             # "-T" means don't send to pager
635 0           my @perldoc_output = map {`perldoc -T $_`} @matching_policies; ## no critic (ProhibitBacktick)
  0            
636 0           _out @perldoc_output;
637              
638 0           exit $EXIT_SUCCESS;
639             }
640              
641             #-----------------------------------------------------------------------------
642              
643             sub _display_version {
644 0     0     _out "$VERSION\n";
645 0           exit $EXIT_SUCCESS;
646             }
647              
648             #-----------------------------------------------------------------------------
649             1;
650              
651             __END__
652              
653             #-----------------------------------------------------------------------------
654              
655             =pod
656              
657             =for stopwords
658             Twitter
659              
660             =head1 NAME
661              
662             Perl::Critic::Command - Guts of L<perlcritic|perlcritic>.
663              
664              
665             =head1 SYNOPSIS
666              
667             use Perl::Critic::Command qw< run >;
668              
669             local @ARGV = qw< --statistics-only lib bin >;
670             run();
671              
672              
673             =head1 DESCRIPTION
674              
675             This is the implementation of the L<perlcritic|perlcritic> command. You can use
676             this to run the command without going through a command interpreter.
677              
678              
679             =head1 INTERFACE SUPPORT
680              
681             This is considered to be a public class. However, its interface is
682             experimental, and will likely change.
683              
684              
685             =head1 IMPORTABLE SUBROUTINES
686              
687             =over
688              
689             =item C<run()>
690              
691             Does the equivalent of the L<perlcritic|perlcritic> command. Unfortunately, at
692             present, this doesn't take any parameters but uses C<@ARGV> to get its
693             input instead. Count on this changing; don't count on the current
694             interface.
695              
696              
697             =back
698              
699              
700             =head1 TO DO
701              
702             Make C<run()> take parameters. The equivalent of C<@ARGV> should be
703             passed as a reference.
704              
705             Turn this into an object.
706              
707              
708             =head1 AUTHOR
709              
710             Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>
711              
712              
713             =head1 COPYRIGHT
714              
715             Copyright (c) 2005-2011 Imaginative Software Systems. All rights reserved.
716              
717             This program is free software; you can redistribute it and/or modify
718             it under the same terms as Perl itself. The full text of this license
719             can be found in the LICENSE file included with this module.
720              
721             =cut
722              
723             ##############################################################################
724             # Local Variables:
725             # mode: cperl
726             # cperl-indent-level: 4
727             # fill-column: 78
728             # indent-tabs-mode: nil
729             # c-indentation-style: bsd
730             # End:
731             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :