Upload
charsbar
View
389
Download
1
Embed Size (px)
Citation preview
Better detection of
what modules are used
by some Perl 5 code
Kenichi Ishigaki
@charsbar
London Perl Workshop 2017
Nov 25, 2017
me
• DBD::SQLite
• CPANTS
• PAUSE on Plack/Mojolicious
• JSON
It's annoying if
prereqs are not
correctly declared
CPANTS has two metrics
to warn this issue
• prereq_matches_use
• build_prereq_matches_use
They usually work,
but sometimes don't # CPANTS mistakenly complains my $template =<<'END'; package [% NAME %]; use Foo::Bar; # should be ignored END
# CPANTS doesn't complain but... use Shiny::New::Loader; # ok load("Something::Else"); # ignored
Other detectors?
• Perl::PrereqScanner
(which uses PPI)
• Perl::PrereqScanner::Lite
(which uses Compiler::Lexer)
Limitation: Test::Kwalitee
Perl::PrereqScanner::
NotQuiteLite
• (usually) faster than Perl::PrereqScanner
• slower than Perl::PrereqScanner::Lite,
but more stable
Target: lib/Perl/PrereqScanner/NotQuiteLite.pm Rate P::PS P::PS::NQL M::EU P::PS::L P::PS 0.999/s -- -87% -95% -97% P::PS::NQL 7.69/s 670% -- -62% -76% M::ExtractUse 20.3/s 1932% 164% -- -36% P::PS::Lite 31.7/s 3073% 312% 56% --
It recognises not
only Moose family
use Moose; extends 'Foo::Bar'; # requires with 'Some::Role'; # requires as well
including MooseX::Declare
use MooseX::Declare; class MyClass extends Foo::Baz with Role { ... }
but also other major frameworks
use Catalyst qw/ My::Module +Fully::Qualified::Plugin::Name /;
use Mojo::Base 'Mojo::Base';
use Dancer2::Plugin; extends('Dancer2::Plugin::ParamTypes');
use Plack::Builder; builder { enable_if { ... } 'MyMiddleware'; };
and more...
aliased autouse later mixin only
prefork superclass unless
Class::Accessor Class::Autouse
Class::Load Inline Module::Runtime
Syntax::Collector Test::Class::Most
Test::Requires
and more...
App::GHPT::Wrapper::OurMoose App::wmiirc::Plugin
Ark Bot::Backbone::Service Bubblegum::Class
CatalystX::Declare Cogwheel
CPAN::Testers::Backend::Base Data::Object::Class
DBICx::Modeler::Model Digital::Driver Elastic::Doc
Fey::ORM::Table Form::Factory::Processor Jedi::App
Momo Moonshine::Magic Moxie Nile::Base
Parse::FixedRecord Pcore Reaction::Class
Reaction::UI::WidgetClass Squirrel Statocles::Base
TAEB::OO Test::Able Test::Roo Web::Simple XML::Rabbit
It distinguishes requires from
recommends and suggests
use Foo; # requires require Bar; # requires as well if (eval "require Baz") { # suggests require Quux; # recommends }
It even knows what
"plan skip_all" means
use Test::More; BEGIN { plan skip_all => "N/A" if $^O ne 'MSWin32'; } use Win32; # recommends
It doesn't really
parse Perl but... • it recognises (long) strings including
here documents
• it accepts utf8 characters as a
subroutine name ( sub λ {...} )
• and new keywords introduced by
Syntax::Feature family ( qs(...) )
CPANTS will eventually
complain if it finds a cheat
q{ use strict; use warnings; }
Migration from
Perl::PrereqScanner
my $pps = Perl::PrereqScanner->new; my $requirements = $pps->scan_file(...); my $nql = Perl::PrereqScanner::NotQuiteLite->new; my $c = $nql->scan_file(...); my $requirements = $c->requires; # or $c->recommends, $c->suggests
Updating cpanfile
scan-perl-prereqs-nqlite ¥ --save-cpanfile ¥ --exclude-core ¥ --recommends ¥ --suggests ¥ --develop
You might want to move some of the
recommends/suggests to requires.
Test::CPANfile
• tests if all the used modules
are listed in cpanfile
• it's ok if cpanfile lists more
than used
• recognises runtime, test, and
configure requirements
Thank you