# best viewed via "perldoc TODO.pod"

=pod

=for stopwords LHS RHS REFACTORINGS FH SVN stopwords

=head1 NAME

Perl::Critic::TODO - Things for Perl::Critic developers to do

=head1 SOURCE

    #######################################################################
    #      $URL: http://perlcritic.tigris.org/svn/perlcritic/branches/Perl-Critic-1.xxx/TODO.pod $
    #     $Date: 2007-08-08 22:25:39 -0700 (Wed, 08 Aug 2007) $
    #   $Author: chrisdolan $
    # $Revision: 1826 $
    #######################################################################

=head1 SEE ALSO

Perl-Critic-More is a separate distribution for less-widely-accepted
policies.  It contains its own TODO.pod.

=head1 NEW FEATURES

=over 4

=item * Report Safari sections in addition to book page numbers.

=item * Allow policies to say that they've had enough and to not use them for the rest of the current document.

Primarily for things like C<RequireUseStrict> and C<ProhibitMagicNumbers>.
Replace current workaround for C<RequireUseStrict>.

=back

=head1 BUGS/LIMITATIONS

=over 4

=item * Modules::RequireVersionVar

Doesn't enforce three-part versions

=item * NamingConventions::ProhibitAmbiguousNames

Don't allow compound names with forbidden words, like "last_record".
Allow forbidden words in RHS of variable declarations

Also, we should make it easeir to add (or delete) words from the
forbbiden list.

=item * Subroutines::ProtectPrivateSubs

Doesn't forbid C<< $pkg->_foo() >> because it can't tell the
difference between that and C<< $self->_foo() >>

=item * ErrorHandling::RequireCarping

This should not complain about using C<warn> or C<die> if it's not in a
function, or if it's not in a non-main:: package.

Also, should allow C<die> when it is obvious that the "message" is a reference.

=item * RegularExpressions::ProhibitCaptureWithoutTest

Allow this construct:

    for ( ... ) {
        next unless /(....)/;
        if ( $1 ) {
            ....
        }
    }

Right now, P::C thinks that the C<$1> isn't legal to use because it's
"outside" of the match.  The thing is, we can only get to the C<if>
if the regex matched.
    while ( $str =~ /(expression)/ )

=item * CodeLayout::ProhibitParensWithBuiltins

Some builtin functions (particularly those that take a variable number of
scalar arguments) should probably get parens.  This policy should be enhanced
to allow the user to specify a list of builtins that are expempt from the
policy.

=item * InputOutput::RequireCheckedOpen and RequireCheckedClose

These policies should not report violations if 'use Fatal' is in effect.

=back

=head1 OTHER PBP POLICIES THAT SEEM FEASIBLE TO IMPLEMENT

Chris Dolan is in the process of implementing the ideas below (but don't let
that stop you from contributing!!!).  That work is supported by a Perl
Foundation grant.  More details about the grant:
L<http://www.perlfoundation.org/april_1_2007_new_grant_awards>

=over 4

=item * InputOutput::RequireChecked* for system calls (p208)

Add policies to ensure checking the return values of system calls.  See
InputOutput::RequireCheckedOpen and InputOutput::RequireCheckedClose.  Needs
to take into account the Fatal and Fatal::Exception modules.

=item * InputOutput::RequireBriefOpen (p209)

Make sure there's a close within N statements of an open, both with
same lexical FH

=item * InputOutput::ProhibitExplicitStdin (p216)

If you're reading from STDIN, chances are you're really wanting to
read from the magic filehandle.

=item * RegularExpressions::RequireBracesForMultiline (p242)

=item * RegularExpressions::ProhibitUnusualDelimiters (p246)

=item * RegularExpressions::ProhibitEscapedMetacharacters (p247)

=item * RegularExpressions::ProhibitEnumeratedClasses (p248)

This will be avoided for ASCII-only code.

=item * RegularExpressions::ProhibitUnusedCapture (p252)

Look for LHS of regexp or use of C<$1>, C<$2>, ... before next
regexp.

=item * RegularExpressions::ProhibitComplexRegexes (p261)

If regexp is longer than N characters/lines, require it be split
into C<qr//> pieces.

Even if the x modifier is used and the regex is split across
multiple lines?

=item * RegularExpressions::ProhibitSingleCharAlternation (p265)

Not sure if this is easy or hard.  Need to look at what PPI emits
for regexps.  Make an exception for qr/ [ ] /x.

=item * RegularExpressions::ProhibitFixedStringMatches (p271)

Can't be C<qr/\s*\\A\s*\((?:\?:)?(?:\s*\w+\s*\|)*\s*\w+\s*\)\s*\\z/>
or C<qr/\s*\\A\s*\w+\s*\\z/>

=back

=head1 NON-PBP POLICIES WANTED

=over 4

=item * TBD::VariableNotUsed

Detect a variable that has a value assigned to it, but never used.

=item * TBD::AllProgramsNeedShebangs

Anything that is a program should have a shebang line.  This includes .t files.

=item * BuiltInFunctions::RequireConstantSprintfFormat

=item * BuiltInFunctions::RequireConstantUnpackFormat

L<http://diotalevi.isa-geek.net/~josh/yapc-lint/slides/slide5.html>

=item * Miscellanea::ProhibitObnoxiousComments

Forbid excessive hash marks e.g. "#### This is a loud comment ####".
Make the obnoxious pattern configurable

=item * ValuesAndExpressions::RequireNotOperator

Require the use of "not" instead of "!", except when this would contradict
ProhibitMixedBooleanOperators.  This may be better suited for
Perl::Critic::More.

=item * Modules::RequireExplicitImporting

Require every C<use> statement to have an explicit import list.  You could
still get around this by calling C<import> directly.

=item * Modules::ForbidImporting

Require every C<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);

=item * ControlStructures::ProhibitIncludeViaDo

Forbid C<do "foo.pl">.  Not sure about this policy name.

=item * Variables::ProhibitUseVars

Disallow C<use vars qw(...)> and require C<our $foo> instead.  This
contradicts Miscellanea::Prohibit5006isms.  Maybe verify C<use 5.6>
before applying this policy.  Low severity.

=item * VariablesAndExpressions::ProhibitQuotedHashKeys

Forbid quotes around hash keys, unless they are really needed.  This
is against what Damian says.  Suggested by Adam Kennedy.  Low
severity.

=item * CodeLayout::ProhibitFunctionalNew

Good: C<< Foo::Bar->new >>, Bad: C<< new Foo::Bar >>

=item * VariablesAndExpressions::RequireConstantVersion (low severity)

=item * VariablesAndExpressions::ProhibitComplexVersion (medium severity)

L<http://rt.cpan.org/Ticket/Display.html?id=20439>

=item * Documentation::RequireSynopsis

=item * Documentation::RequireLicense

These are simplified versions of Documentation::RequirePodSections.

=item * Miscellaneous::ProhibitBoilerplate

Complain about copy-and-paste code or docs from h2xs, Module::Starter::*,
etc.

Here's a non-PPI implementation:
L<http://search.cpan.org/src/JJORE/Carp-Clan-5.8/t/04boilerplate.t>

=item * BuiltinFunctions::ProhibitExtraneousScalarCall

Recommend that C<if (scalar @array)> be rewritten as C<if (@array)>.

=back

=head1 REFACTORINGS and ENHANCEMENTS

=over 4

=item * Create constants for the PPI location array elements.

=item * MOVE THE LINE-DISABLING INTO P::C::Document

All the code that deals with finding all the '##no critic' comments and noting
which policies are disabled at each line seems like it would be better placed
in Perl::Critic::Document.  P::C::Document could then provide methods to
indicate if a policy is disabled at a particular line.  So the basic algorithm
in Perl::Critic might look something like this:

  foreach $element (@PPI_ELEMENTS) {
     foreach $policy (@POLICIES) {
        $line = $element->location->[0];
        next if $doc->policy_is_disabled_at_line( $policy, $line );
        push @violations, $policy->violates( $elem, $doc );
     }
  }

=item * Some means of detecting "runnaway" C<##no critic>

Elliot was talking to a couple of users at ETech and one of their major
concerns was that they were using C<##no critic> and forgetting to do a
C<##use critic> after the problematic section.  Perhaps an option to
F<perlcritic> to scan for such things is in order.

=item * 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.

=item * Allow more flexible Policy parameter parsing

Several policies use C<words_from_string()> to split their parameters into
words.  This function is currently limited to splitting on whitespace.  It
would be nice to allow some lattitude for users who might try and use commas
or some other kind of delimiter.

=item * Enhance P::C::critique() to accept files, directories, or code strings

Just like F<bin/perlcritic> does now.

=item * Add C<-cache> flag to F<bin/perlcritic>

If enabled, this turns on L<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 cachedir should perhaps include the PPI version number!  At least
until PPI incorporates its own version number in the cache.

(see F<t/40_criticize.t> for a more robust implementation)

=item * Use hash-lookup instead of C<List::MoreUtils::any> function.

In several places, Perl::Critic uses C<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] }; }

=back

=head1 PPI BUGS

We're waiting on the following bugs to get fixed in a CPAN release of PPI:

=over 4

=item literal()

ValuesAndExpressions::RequireNumberSeparators uses a stringy eval to
numify.  Current PPI SVN has code for the
PPI::Token::Number->literal() method which numifies from source.  When
we depend on a PPI version higher than 1.118, the _to_number()
function in that policy can be removed in favor of literal().

=item 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 mixde newlines anytime soon.

=item Anonymous constructors in lists

The following parses wrong in PPI v1.118.  A PPI fix is in progress.

  bless( {} );

When this is fixed, uncomment a few tests in t/20_policies_classhierarchies.t

=item Hash constructors with a parenthesis directly to the left.

The L<PPI::Statement> surrounding the L<PPI::Constructor> returns undef
for C<location()> for the following:

  ({})

The same problem exists for

  ({} )

but not for

  ( {})

Logged as RT #23788.

Remove trinary operator usage in RequireUseStrict, RequireUseWarnings, and
RequireExplicitPackage once this is fixed.

=item L<PPI::Structure::Block>s being generated instead of L<PPI::Structure::Constructor>

For complicated data structures, C<< { blah => blah } >> will result in a
L<PPI::Structure::Block> being created, instead of a
L<PPI::Structure::Constructor>.

ValuesAndExpressions::ProhibitCommaSeparatedStatements and other policies have
workarounds for this.

=item 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.

=back

=cut

##############################################################################
# Local Variables:
#   mode: cperl
#   cperl-indent-level: 4
#   fill-column: 78
#   indent-tabs-mode: nil
#   c-indentation-style: bsd
# End:
# ex: set ts=8 sts=4 sw=4 tw=78 ft=pod expandtab :
