1

How do I run Perl critic from a script with Subroutines::ProhibitExcessComplexity enabled ? I tried the following but it wasn't flagging complex 500+ line subroutines. I do not have a .perlcriticrc(Neither do I want one to be there)

use Perl::Critic;

run_critic('temp.pl');
exit;

sub run_critic {
    my $file   = shift;
    my $critic = Perl::Critic->new(
        -severity => 5,
        -policy   => 'Subroutines::ProhibitExcessComplexity',
        -verbose  => 5,
    );
    my @violations = $critic->critique($file);
    print @violations;
}

My Perl::Critic version is 1.116

perl -MPerl::Critic -e 'print "$Perl::Critic::VERSION\n"'
1.116
Jean
  • 21,665
  • 24
  • 69
  • 119

3 Answers3

2

View the loaded Policies

To view the policies that are actually loaded, use Perl::Critic->policies.

policies()

Returns a list containing references to all the Policy objects that have been loaded into this engine. Objects will be in the order that they were loaded. If you view your policies, you can see it's not being added:

You will see your desired policy isn't added to the list:

use strict;
use warnings;

use Perl::Critic;

run_critic($0);
exit;

sub run_critic {
    my $file   = shift;
    my $critic = Perl::Critic->new(
        -severity => 5,
        -policy   => 'Subroutines::ProhibitExcessComplexity',
        -verbose  => 5,
    );
    print $critic->policies();      # View loaded Policies

    my @violations = $critic->critique($file);
    print @violations;
}

Outputs:

BuiltinFunctions::ProhibitSleepViaSelect
BuiltinFunctions::ProhibitStringyEval
BuiltinFunctions::RequireGlobFunction
ClassHierarchies::ProhibitOneArgBless
ControlStructures::ProhibitMutatingListFunctions
InputOutput::ProhibitBarewordFileHandles
InputOutput::ProhibitInteractiveTest
InputOutput::ProhibitTwoArgOpen
InputOutput::RequireEncodingWithUTF8Layer
Modules::ProhibitEvilModules
Modules::RequireBarewordIncludes
Modules::RequireFilenameMatchesPackage
Subroutines::ProhibitExplicitReturnUndef       
Subroutines::ProhibitNestedSubs
Subroutines::ProhibitReturnSort
Subroutines::ProhibitSubroutinePrototypes
TestingAndDebugging::ProhibitNoStrict
TestingAndDebugging::RequireUseStrict
ValuesAndExpressions::ProhibitLeadingZeros
Variables::ProhibitConditionalDeclarations
Variables::RequireLexicalLoopIterators

Proper Configuration option: -include

The problem is that the Constructor option -policy does not exist.

Instead you want to use -include:

-include is a reference to a list of string @PATTERNS. Policy modules that match at least one m/$PATTERN/ixms will always be loaded, irrespective of all other settings. For example:

Therefore fixing your constructor:

    my $critic = Perl::Critic->new(
        -severity => 5,
        -include  => 'Subroutines::ProhibitExcessComplexity',
        -verbose  => 5,
    );

Outputs:

BuiltinFunctions::ProhibitSleepViaSelect
BuiltinFunctions::ProhibitStringyEval
BuiltinFunctions::RequireGlobFunction
ClassHierarchies::ProhibitOneArgBless
ControlStructures::ProhibitMutatingListFunctions
InputOutput::ProhibitBarewordFileHandles
InputOutput::ProhibitInteractiveTest
InputOutput::ProhibitTwoArgOpen
InputOutput::RequireEncodingWithUTF8Layer
Modules::ProhibitEvilModules
Modules::RequireBarewordIncludes
Modules::RequireFilenameMatchesPackage
Subroutines::ProhibitExcessComplexity           # <--- ta da
Subroutines::ProhibitExplicitReturnUndef
Subroutines::ProhibitNestedSubs
Subroutines::ProhibitReturnSort
Subroutines::ProhibitSubroutinePrototypes
TestingAndDebugging::ProhibitNoStrict
TestingAndDebugging::RequireUseStrict
ValuesAndExpressions::ProhibitLeadingZeros
Variables::ProhibitConditionalDeclarations
Variables::RequireLexicalLoopIterators
Miller
  • 34,962
  • 4
  • 39
  • 60
  • 1
    It seems like -severity is ignored with -include. Do you see that behavior? – toolic Oct 22 '14 at 20:57
  • 2
    @toolic Ah, just found where this is described in the [documentation](https://metacpan.org/pod/Perl::Critic#new): "Policy modules that match at least one `m/$PATTERN/ixms` will always be loaded, **irrespective of all other settings.** For example: `my $critic = Perl::Critic->new(-include => ['layout'] -severity => 4);` This would cause `Perl::Critic` to apply all the `CodeLayout::*` Policy modules even though they have a severity level that is less than 4." (emphasis added) – ThisSuitIsBlackNot Oct 22 '14 at 21:04
  • @ThisSuitIsBlackNot: ++ I saw that, too, but I stopped reading too soon. So -severity is irrelevant w/ -include. This answer should be updated with this info. – toolic Oct 22 '14 at 21:07
1

Subroutines::ProhibitExcessComplexity has a severity of 3 (as seen from the source code), but you are using 5. This means you are only showing violations of severity=5. Set the -severity to 1, 2 or 3:

my $critic = Perl::Critic->new(-severity => 1);

Also note that -policy is not an option for new in the POD; it is ignored.

toolic
  • 57,801
  • 17
  • 75
  • 117
  • It works for me if I use either `-single-policy` or `-include` and `-severity => 5`. – ThisSuitIsBlackNot Oct 22 '14 at 20:03
  • (In other words, the issue with the OP's code was the `-policy` option, not `-severity`.) – ThisSuitIsBlackNot Oct 22 '14 at 20:18
  • @ThisSuitIsBlackNot: My code works for me. I'm using an older version (1.111), however. It should depend on the severity. – toolic Oct 22 '14 at 20:53
  • Your code works for me, too; I wasn't saying it's wrong, just that the real cause of the OP's error was using the non-existent `-policy` option instead of `-single-policy` or `-include`. I agree that the severity *should* affect it, but it doesn't seem to in my tests (at least on v1.122). – ThisSuitIsBlackNot Oct 22 '14 at 20:58
  • -policy is ignored by new(). -foo is also ignored by new(). If I leave -policy in (which is not desirable), and I change the severity to 1, then it works. Maybe it's TIMTOWTDI. – toolic Oct 22 '14 at 21:04
  • But you're also loading *all* policies (assuming the OP doesn't have a `.perlcriticrc` file, which is what they said in the comments earlier). Using `-include` only loads the specified policies, which seems to be what the OP is trying to do. – ThisSuitIsBlackNot Oct 22 '14 at 21:07
  • Of course, on re-reading the question, they just say they want to enable the policy, not that they want to enable *only* that policy, so perhaps I'm interpreting it wrong. – ThisSuitIsBlackNot Oct 22 '14 at 21:08
1

I would recommend using the perlcritic utility instead. It can do nice things like colorize the output or send it to a pager for you. Then you can wrap it with a shell script, alias, or backticks, or a system() call or whatever you like.

# Analyze with just the ProhibitExcessComplexity policy
perlcritic --single-policy=ProhibitExcessComplexity FILES_OR_DIRECTORIES

# Analyze with all severity 5 policies, plus ExcessComplexity
perlcritic --severity=5 --include=ProhibitExcessComplexity FILES_OR_DIRECTORIES