$s = <<'EOF';
perl_checker
Goals of perl_checker
- for beginners in perl:
based on what the programmer is writing,
- suggest better or more standard ways to do the same
- detect wrong code
=> a kind of automatic teacher
- for senior programmers:
detect typos, unused variables, check number
of parameters, global analysis to check method calls...
- enforce the same perl style by enforcing a subset of perl of features.
In perl There is more than one way to do it.
In perl_checker's subset of Perl, there is not too many ways to do it.
This is especially useful for big projects.
(NB: the subset is chosen to keep a good expressivity)
Compared to Perl-Critic
- perl_checker use its own OCaml-written perl parser, which is in no way as robust as PPI.
A PPI require is to be able to parse non finished perl documents.
perl_checker is a checker, and it is not a big deal to die horribly on a weird perl expression, telling the programmer what to write instead.
- perl_checker is much faster (more than 100 times) (ML pattern matching rulez)
- perl_checker checks a lot more things than perlcritic: undeclared variables, unknown functions, unknown methods...
- and of course perl_checker checks are different from the Conways's Perl Best Practices
Get it
CVS source
Implemented features
- white space normalization
- enforce a similar coding style. In many languages you can find a coding
style document (eg: the GNU one).
TESTS=force_layout.t
- disallow complex expressions
- perl_checker try to ban some weird-not-used-a-lot features.
TESTS=syntax_restrictions.t
- suggest simpler expressions
- when there is a simpler way to write an expression, suggest it. It can
also help detecting errors.
TESTS=suggest_better.t
- context checks
- Perl has types associated with variables names, the so-called "context".
Some expressions mixing contexts are stupid, perl_checker detects them.
TESTS=context.t
- function call check
- detection of unknown functions or mismatching prototypes (warning: since
perl is a dynamic language, some spurious warnings may occur when a function
is defined using stashes).
TESTS=prototype.t
- method call check
- detection of unknown methods or mismatching prototypes. perl_checker
doesn't have any idea what the object type is, it simply checks if a method
with that name and that number of parameters exists.
TESTS=method.t
- return value check
- dropping the result of a functionnally pure function is stupid.
using the result of a function returning void is stupid too.
TESTS=return_value.t
- detect some Perl traps
- some Perl expressions are stupid, and one gets a warning when running
them with perl -w. The drawback are perl -w is the lack of
code coverage, it only detects expressions which are evaluated.
TESTS=various_errors.t
Todo
Functionalities that would be nice:
- add flow analysis
- maybe a "soft typing" type analysis
- detect places where imperative code can be replaced with
functional code (already done for some simple loops)
- check the number of returned values when checking prototype compliance
EOF
my $_rationale = <<'EOF';
Rationale
Perl is a big language, there is ThereIsMoreThanOneWayToDoIt.
It has advantages but also some drawbacks for team project:
- it is hard to learn every special rules. Automatically enforced syntax
coding rules help learning incrementally
EOF
use lib ('test', '..');
use read_t;
sub get_example {
my ($file) = @_;
my @tests = read_t::read_t("test/$file");
$file =~ s|test/||;
qq(
\n) .
join('', map {
my $lines = join("
", map { "" . html_quote($_) . "" } @{$_->{lines}});
my $logs = join("
", map { html_quote($_) } @{$_->{logs}});
" \n", $lines, " | ", $logs, " |
\n";
} @tests) .
"
\n";
}
sub anchor_to_examples {
my ($s) = @_;
$s =~ s!TESTS=(\S+)!(examples)!g;
$s;
}
sub fill_in_examples {
my ($s) = @_;
$s =~ s!TESTS=(\S+)!get_example($1)!ge;
$s;
}
$s =~ s!Implemented features
(.*)!
"Implemented features
" . anchor_to_examples($1) .
"Examples
" . fill_in_examples($1) .
""!se;
print $s;
sub html_quote {
local $_ = $_[0];
s/</g;
s/>/>/g;
s/^(\s*)/" " x length($1)/e;
$_;
}