App-perl-distrolint
view release on metacpan or search on metacpan
lib/App/perl/distrolint.pm view on Meta::CPAN
class App::perl::distrolint;
use List::Util qw( max );
use Module::Pluggable::Object;
use String::Tagged::Terminal;
use App::perl::distrolint::Config;
=head1 NAME
C<App::perl::distrolint> - distribution-wide linting tools for Perl distributions
=head1 SYNOPSIS
=for highlighter perl
use App::perl::distrolint;
exit App::perl::distrolint->new->run( @ARGV );
=head1 DESCRIPTION
This module implements an application for applying various code-linting tests
across the source code for an entire Perl distribution. The individual checks
performed are described more in the various C<App::perl::distrolint::Check::*>
modules.
At present in this very early version, many of these checks are very
opinionated, doing things specific to the way I personally lay out my code.
This distribution currently exists largely to allow people to see the kinds of
things that are possible, and also acts as a demonstration of the use of
L<Text::Treesitter> and F<tree-sitter-perl> to be used as a static linting
tool for Perl source code.
A limited amount of customisation and configuration can be performed on a
per-project or per-user basis, by writing settings into F<distrolint.ini>
files. This is described in more detail in C<App::perl::distrolint::Config>.
=cut
my $finder = Module::Pluggable::Object->new(
search_path => [qw( App::perl::distrolint::Check )],
require => 1,
);
my %COL = (
red => 1,
green => 2,
yellow => 3,
);
my %FORMAT = (
bullet => { bold => 1, fgindex => $COL{yellow} },
pass => { bold => 1, fgindex => $COL{green} },
fail => { bold => 1, fgindex => $COL{red} },
note => { fgindex => $COL{yellow} },
diag => {},
file => { italic => 1 },
literal => { altfont => 1 },
);
my $PASS = String::Tagged::Terminal->new_tagged( "PASS", $FORMAT{pass}->%* );
my $FAIL = String::Tagged::Terminal->new_tagged( "FAIL", $FORMAT{fail}->%* );
my $notecount;
method run ( @argv )
{
my @checks = $self->checks;
my $namelen = max map { length $_->{name} } @checks;
my $totalcount = 0;
my $passcount = 0;
$notecount = 0;
foreach my $check ( @checks ) {
App::perl::distrolint::Config->is_check_enabled( $check->{name} ) or
next;
my $name = $check->{name};
$name .= "." x ($namelen - length $name);
String::Tagged::Terminal->new
->append( " " )
->append_tagged( "*", $FORMAT{bullet}->%* )
->append( sprintf " %s (%s)", $name, $check->{desc} )
->say_to_terminal;
my $ok = $check->{obj}->run( $self );
String::Tagged::Terminal->from_sprintf( " -- %s",
$ok ? $PASS : $FAIL
)->say_to_terminal;
$totalcount++;
$passcount++ if $ok;
}
print "\n";
printf "%d of %d checks passed", $passcount, $totalcount;
printf " (%d FAILed)", $totalcount - $passcount if $passcount < $totalcount;
printf " (and %d notes)", $notecount if $notecount;
print "\n";
return 1 if $passcount < $totalcount;
return 2 if $notecount;
return 0;
}
method checks ()
{
my @checks = map {
my $pkg = $_;
{
obj => $pkg->new,
name => $pkg =~ s/^App::perl::distrolint::Check:://r,
desc => $pkg->DESC,
sort => $pkg->SORT,
( run in 2.588 seconds using v1.01-cache-2.11-cpan-5735350b133 )