NAME
Perl::Critic::TODO - Things for Perl::Critic developers to do
SOURCE
$URL: http://perlcritic.tigris.org/svn/perlcritic/trunk/distributions/Perl-Critic/TODO.pod $
$Date: 2009-02-14 12:12:34 -0600 (Sat, 14 Feb 2009) $
$Author: clonezone $
$Revision: 3113 $
SEE ALSO
Perl-Critic-More is a separate distribution for less-widely-accepted policies. It contains its own TODO.pod.
NEW FEATURES
Report PBP and Safari sections in addition to PBP page numbers.
Something like
Readonly::Scalar my $EXPL => { pbp_pages => [ 57 ], pbp_section => '5.2', safari_section => something, };
Include PBP references and Safari sections in the documentation.
Perhaps these could be injected into the POD at build time, based on the data in the code. But that data is not entirely static, so I'm not sure how it would work for Policies that dynamically determine the PBP references.
Perhaps it would be good enough to just create a one-off tool that would inject the PBP and/or Safari references into the POD one time, and we could manually deal with Policies that behave oddly.
Much better would be to put the information in the POD in a structured manner and parse it out in the code, something along the lines of
=head1 METADATA =over =item Default Themes core bugs pbp =item Default Severity 3 =item Perl Best Practices Page Numbers 193, 195 =back
and so on.
Add --files-with-violations/-l and --files-without-violations/-L options to perlcritic.
Just print out file names. I could have used this at work when combined with
--single-policy
.gvim `perlcritic --single-policy QuotedWordLists -l`
Add a file Parameter::Behavior.
Allow values of (at least) string-list Parameters to be specified in a file.
For the benefit of PodSpelling, etc.
Enhance string-list Behavior to allow specification of delimiters.
For things like RequirePodSections.
Add queries to --list option to perlcritic.
List Policies based upon severity, theme, and (what I want this second) applies_to.
Add formatting of --list output.
Support Jeff Bisbee's use case (he dumps all the policies in severity order with full descriptions and other metadata).
Support for
#line 123 "filename"
directives.For code generators and template languages that allow inline Perl code.
Yes, somebody has an in-house templating system where they've written a custom test module that extracts the perl code from a template and critiques it.
Actually, this would be useful for programs: Module::Build "fixes" shebang lines so that there's the bit about invoking perl if the program is attempted to be run by a Bourne shell, which throws the line numbers off when using Test::P::C on the contents of a
blib
directory.This has been implemented in PPI, but hasn't been released yet. When it does come out, we need to change the line and file reported by Violations.
Enhance statistics.
- Blank line count
- POD line count
- Comment line count
- Data section count
Detect 5.10 source and enable stuff for that.
For example, treat
say
as equivalent toprint
.Support a means of failing if a Policy isn't installed.
For example, the self compliance test now depends upon a Policy in the More distribution.
Something like using a "+" sign in front of the Policy name in its configuration block, analogous to the "-" sign used for disabling a policy, e.g. "
[+Example::Policy]
".Threading
Pretty obviously, Perl::Critic is readily parallelizable, just do a document per thread. ("readily" being conceptual, not necessarily practical) Although there's now
Policy::prepare_to_scan_document()
, given perl's thread data sharing model, this shouldn't be an issue.Add support in .run files for regexes for violation descriptions.
Add support for "## use critic (blah)".
If I've got:
## no critic (SomePolicy) ... ## no critic (ADifferentPolicy) ... ## no critic (YetAnotherPolicy)
If I want to turn
YetAnotherPolicy
back on but neitherSomePolicy
norADifferentPolicy
, I've got to do this:## use critic ## no critic (SomePolicy, ADifferentPolicy)
Why can't I do this:
## use critic (SomeOtherPolicy)
Make color work on Windows.
Use Win32::Console::ANSI like App::Ack.
A function that splits up a PPI::Node's descendants based upon package.
This is necessary to get P::C::Moose Policies correct.
Say we've got the following code:
#!perl my $x = blah(); package Foo; my $y = blah_blah(); { say 'Whee!'; package Bar; something(); } thingy(); package Baz; da_da_da(); package Foo; foreach ( blrfl() ) { ... }
Calling the function on a PPI::Document for the above should return a hash of arrays of PPI::Nodes. The result should look something like this, using multi-line string literals (RestrictLongStrings violations!) for the actual code parts instead of PPI trees to make this easier to read.
( main => [ q< #!perl my $x = blah(); >, ], Foo => [ q< package Foo; my $y = blah_blah(); { say 'Whee!'; } thingy(); >, q< package Foo; foreach ( blrfl() ) { ... } >, ], Bar => [ q< package Bar; something(); >, ], Baz => [ q< package Baz; da_da_da(); >, ], )
Use version to declare
$VERSION
numbers throughout P::CPBP recommends using the version module. I chose not to follow that recommendation because version didn't work with the Perl v5.6.1 that I had at $work at that time (and I really wanted to use Perl::Critic at work). But now the version has been updated and those bugs may have been fixed, or perhaps we just don't care about running on Perl v5.6.1 any more. So maybe now we can go ahead and use version.
BUGS/LIMITATIONS
Document bugs for individual Policies in the Policies themselves. Users should be aware of limitations. (And, hey, we might get patches that way.)
OTHER PBP POLICIES THAT SEEM FEASIBLE TO IMPLEMENT
Modules::RequireUseVersion [405-406]
Modules::RequireThreePartVersion [405-406]
NamingConventions::RequireArrayAndHashReferenceVariablesEndWith_Ref [41-42]
Check for
$variable = [...]
,$variable = {...}
,$variable->[...]
, and$variable->{...}
.Objects::ProhibitRestrictedHashes [322-323]
Look for use of the bad methods in Hash::Util.
Objects::ProhibitLValueAccessors [346-349]
Look for the
:lvalue
subroutine attribute.Objects::ProhibitIndirectSyntax [349-351]
While the general situation can't be handled, we can look for a configured set of names. Especially should be able to complain about
new Foo()
by default.
NON-PBP POLICIES WANTED
Subroutines::RequireArgumentValidation
Enforce the use of Params::Validate or Params::Util or some other argument validation mechanism. This could be one Policy that can be configured for different validation mechanisms, or we could have a separate Policy for each mechanism, and let the user choose which one they want to use (I think I prefer the later).
NamingConventions::ProhibitMisspelledSymbolNames
The idea behind this policy is to encourage better names for variables and subroutines by enforcing correct spelling and prohibiting the use of home-grown abbreviations. Assuming that the author uses underscores or camel-case, it should be possible to split symbols into words, and then look them up in a dictionary (see PodSpelling). This policy should probably have a similar stopwords feature as well.
Documentation::RequireModuleAbstract
Require a
=head1 NAME
POD section with content that matches\A \s* [\w:]+ \s+ - \s+ \S
. The single hyphen is the important bit. Also, must be a single line.Expressions::RequireFatCommasInHashConstructors
ErrorHandling::RequireLocalizingGlobalErrorVariablesInDESTROY
Prevent
$.
,$@
,$!
,$^E
, and$?
from being cleared unexpectedly by DESTROY methods.package Foo; sub DESTROY { die "Died in Foo::DESTROY()"; } package main; eval { my $foo = Foo->new(); die "Died in eval." } print $@; # "Died in Foo::DESTROY()", not "Died in eval.".
See http://use.perl.org/~Ovid/journal/36767 and http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2008-06/msg00542.html.
Expressions::ProhibitDecimalWithBitwiseOperator
Expressions::ProhibitStringsWithBitwiseOperator
InputOutput::ProhibitMagicDiamond
Steal the idea from B::Lint.
NamingConventions::RequireArrayAndHashReferenceVariablesEndWith_Ref
Programs::RequireShebang
Anything that is a program should have a shebang line. This includes .t files.
BuiltInFunctions::RequireConstantSprintfFormat
BuiltInFunctions::RequireConstantUnpackFormat
http://diotalevi.isa-geek.net/~josh/yapc-lint/slides/slide5.html
Miscellanea::ProhibitObnoxiousComments
Forbid excessive hash marks e.g. "#### This is a loud comment ####". Make the obnoxious pattern configurable
ValuesAndExpressions::RequireNotOperator
Require the use of "not" instead of "!", except when this would contradict ProhibitMixedBooleanOperators. This may be better suited for Perl::Critic::More.
ValuesAndExpressions::ProhibitUnusedReadonlyConstants
We'll only be able to look at lexicals. For similar reasons, we can't do anything about constant.
Modules::RequireExplicitImporting
Require every
use
statement to have an explicit import list. You could still get around this by callingimport
directly.Modules::ForbidImporting
Require every
use
to have an explicitly empty import list. This is for folks who like to see fully-qualified function names. Should probably provide a list of exempt modules (like FindBin);ControlStructures::ProhibitIncludeViaDo
Forbid
do "foo.pl"
. Not sure about this policy name.Variables::ProhibitUseVars
Disallow
use vars qw(...)
and requireour $foo
instead. This contradicts Miscellanea::Prohibit5006isms. Maybe verifyuse 5.6
before applying this policy. Low severity.VariablesAndExpressions::ProhibitQuotedHashKeys
Forbid quotes around hash keys, unless they are really needed. This is against what Damian says. Suggested by Adam Kennedy. Low severity.
CodeLayout::ProhibitFunctionalNew
Good:
Foo::Bar->new
, Bad:new Foo::Bar
RegularExpressions::ProhibitSWSWSW
Require
split
instead ofm/\s*\w*\s*\w*\s*/
. From MJD's Red Flags.VariablesAndExpressions::RequireConstantVersion (low severity)
VariablesAndExpressions::ProhibitComplexVersion (medium severity)
Documentation::RequireSynopsis
Documentation::RequireLicense
These are simplified versions of Documentation::RequirePodSections.
Documentation::RequireValidSynopsis
The Synopsis section must be all indented and must be syntactically valid Perl (as validated by PPI).
Documentation::ProhibitEmptySections
Any
=headN
and=over
sections must not be empty. This helps catch boilerplate (although Test::Pod should catch empty=over
blocks).On the other hand,
=item ...
sections can be empty, since the item label is content.Miscellaneous::ProhibitBoilerplate
Complain about copy-and-paste code or docs from h2xs, Module::Starter::*, etc.
Here's a non-PPI implementation: http://search.cpan.org/src/JJORE/Carp-Clan-5.8/t/04boilerplate.t
NamingConventions::ProhibitPackagesSubroutinesAndBarewordFileHandlesWithTheSameNames
See http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2009-01/msg00685.html.
BuiltinFunctions::ProhibitExtraneousScalarCall
Recommend that
if (scalar @array)
be rewritten asif (@array)
.RegularExpressions::ProhibitMixedDelimiters
Ban s{foo}(bar)
RegularExpressions::ProhibitScalarAsRegexp
Ban naked strings as regexps, like:
print 1 if $str =~ $regexp;
Instead, it should be:
print 1 if $str =~ m/$regexp/;
or
print 1 if $str =~ m/$regexp/xms;
ValuesAndExpressions::RequireInterpolatedStringyEval
Ensure that the argument to a stringy eval is not a constant string. That's just wasteful. Real world examples include:
eval 'use Optional::Module';
which is better written as
eval { require Optional::Module; Optional::Module->import };
for performance gains and compile-time syntax checking.
RegularExpressions::ProhibitUnnecessaryEscapes
Complain if user puts a backslash escape in front of non-special characters. For example:
m/\!/;
Make exceptions for
\"
,\'
and\`
since those are often inserted to workaround bugs in syntax highlighting.Note that this is different inside character classes, where only
^
,]
and-
need to be escaped, I think. Caret only needs to be escaped at the beginning, and dash does NOT need to be escaped at the beginning and end. See perlreref.Steal ideas from Dunce::Files.
Can someone expand this entry, please?
ControlStructures::ProhibitAssigmentInConditional
ValuesAndExpressions::RequireConstantBeforeEquals
ValuesAndExpressions::RequireConstantBeforeOperator
http://use.perl.org/~stu42j/journal/36412
Just about everyone has been bitten by
if ($x = 10) { ... }
when they meant to use==
. A safer style is10 == $x
because omitting the second=
yields a noisy compile-time failure instead of silent runtime error.ProhibitAssigmentInConditional complains if the condition of a while, until, if or unless is solely an assignment. If it's anything more complex (like
if (($x=10)){}
orwhile ($x=$y=$z){}
), there is no warning.RequireConstantBeforeEquals complains if the left side of an
==
is a variable while the right side is a constant.RequireConstantBeforeOperator complains if the left side of any comparison operator (
==
,eq
,<
, etc) is a variable while the right side is a constant.InputOutput::ProhibitUTF8IOLayer
http://www.perlfoundation.org/perl5/index.cgi?the_utf8_perlio_layer
BuiltinFunctions::ProhibitExit(?:InModules)?
Forbid
exit()
in files that lack a shebang. Inspired by http://use.perl.org/~Ovid/journal/36746 and an analogous checker in FindBugs.Modules::ProhibitRedundantLoading
Don't allow a package to "use" the same module more than once, unless there is a "no <module>" between them.
See https://rt.cpan.org/Ticket/Display.html?id=38074.
ErrorHandling::RequireLocalizingEVAL_ERRORInDESTROY
The opposite side of ErrorHandling::RequireCheckingReturnValueOfEval.
Documentation::RequirePODLinksIncludeText
The whole problem with "on the Foo manpage" being fixed by L<Foo|Foo>.
REFACTORINGS and ENHANCEMENTS
Refactor guts of perlcritic into Perl::Critic::CLI
So the perlcritic script would basically just say...
use Perl::Critic::CLI; exit Perl::Critic::CLI->run(@ARGV);
This would make the stuff that is currently inside perlcritic easier to test. Also would open the door for developers to subclass and extend perlcritic, if they had some reason to do so. Also, just because it feels like the right thing to do.
Create constants for the PPI location array elements.
Some means of detecting "runaway"
##no critic
Elliot was talking to a couple of users at ETech and one of their major concerns was that they were using
##no critic
and forgetting to do a##use critic
after the problematic section. Perhaps an option to perlcritic to scan for such things is in order.Change API to use named parameters
Most of the methods on the public classes use named parameters for passing arguments. I'd like to extend that pattern to include all object-methods. Static methods can still use positional parameters.
Enhance P::C::critique() to accept files, directories, or code strings
Just like bin/perlcritic does now.
Add
-cache
flag to bin/perlcriticIf enabled, this turns on PPI::Cache:
require PPI::Cache; my $cache_path = "/tmp/test-perl-critic-cache-$ENV{USER}"; mkdir $cache_path, oct 700 if (! -d $cache_path); PPI::Cache->import(path => $cache_path);
This cache directory should perhaps include the PPI version number! At least until PPI incorporates its own version number in the cache.
(see t/40_criticize.t for a more robust implementation)
Use hash-lookup instead of
List::MoreUtils::any
function.In several places, Perl::Critic uses
List::MoreUtils::any
to see if a string is a member of a list. Instead, I suggest using a named subroutine that does a hash-lookup like this:my %logical_ops = hashify( qw( ! || && ||= &&= and or not ) ); sub is_logical_op { return exists $logical_ops{ $_[0] }; }
Question: Why?
Answer: Readability, mostly. Performance, maybe.
Refactor guts of perlcritic into a module (Perl::Critic::App ??)
Because it is getting unwieldy in there.
PPI BUGS
We're waiting on the following bugs to get fixed in a CPAN release of PPI:
- PPI::Token::descendant_of()
-
Exists in svn. Replace _descendant_of() in RequireCheckingReturnValueOfEval with that, once it is released, because it's faster and native.
- Newlines
-
PPI does not preserve newlines. That makes CodeLayout::RequireConsistentNewlines impossible to implement under PPI. For now, it's implemented by pulling the source out of the file and skipping PPI.
It's unlikely that PPI will support mixed newlines anytime soon.
- Operators
-
ValuesAndExpressions::ProhibitMismatchedOperators has two workarounds for PPI bugs with parsing operators. Many of these bugs have been fixed in PPI, so it would be good to check if those workarounds are still needed.
- Regexp methods
-
Not strictly a bug -- the PPI Regexp classes have a dearth of accessor methods as of v1.118, meaning that we have to do messy digging into internals. I wrote Perl::Critic:Utils::PPIRegexp to encapsulate this messiness, but it would be nicer to have an official interface in PPI.
- QuoteLike::Words in the place of a ForLoop
-
PPI incorrectly parses
<for qw<blah
{}>>.