| 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 : |