use strict;
{
$Perl::PrereqScanner::Scanner::Perl5::VERSION = '1.011';
}
use Moose;
# ABSTRACT: scan for core Perl 5 language indicators of required modules
sub scan_for_prereqs {
my ($self, $ppi_doc, $req) = @_;
# regular use and require
my $includes = $ppi_doc->find('Statement::Include') || [];
for my $node ( @$includes ) {
# minimum perl version
if ( $node->version ) {
$req->add_minimum(perl => $node->version);
next;
}
# skip lib.pm
# lib.pm is not indexed in 02packages, so listing it as a prereq is not a
# good idea. -- rjbs, 2011-08-17
next if grep { $_ eq $node->module } qw{ lib };
# inheritance
if (grep { $_ eq $node->module } qw{ base parent }) {
# rt#55713: skip arguments to base or parent, focus only on inheritance
my @meat = grep {
$_->isa('PPI::Token::QuoteLike::Words')
|| $_->isa('PPI::Token::Quote')
} $node->arguments;
my @parents = map { $self->_q_contents($_) } @meat;
$req->add_minimum($_ => 0) for @parents;
}
# regular modules
my $version = $node->module_version ? $node->module_version->content : 0;
# rt#55851: 'require $foo;' shouldn't add any prereq
next unless $node->module;
# See if the next statement after require is Module->VERSION(min):
$version = $self->_check_required_version($node) || 0
if not $version and $node->type eq 'require';
$req->add_minimum($node->module, $version);
}
}
# For "require Module", see if the next statement is Module->VERSION(min):
sub _check_required_version {
my ($self, $node) = @_;
my $next = $node->snext_sibling;
return unless $next and $next->class eq 'PPI::Statement';
my ($invocant, $op, $method, $list, $too_much) = $next->schildren;
return unless defined $list # need enough children
and $op->class eq 'PPI::Token::Operator'
and $op->content eq '->'
and $method->content eq 'VERSION'
and (not defined $too_much # but not too many children
or $too_much->content eq ';')
and $invocant->content eq $node->module
and $list->class eq 'PPI::Structure::List'
and $list->braces eq '()'
and $list->schildren == 1;
my $exp = $list->schild(0);
return unless $exp->class eq 'PPI::Statement::Expression'
and $exp->schildren == 1;
my $arg = $exp->schild(0);
if ($arg->isa('PPI::Token::Number')) {
return $arg->content;
} elsif ($arg->isa('PPI::Token::Quote') and $arg->can('literal')) {
return $arg->literal;
}
return; # No minimum version found
} # end _check_required_version
1;
__END__
=pod
=head1 NAME
Perl::PrereqScanner::Scanner::Perl5 - scan for core Perl 5 language indicators of required modules
=head1 VERSION
version 1.011
=head1 DESCRIPTION
This scanner will look for the following indicators:
=over 4
=item *
plain lines beginning with C<use> or C<require> in your perl modules and scripts, including minimum perl version
=item *
regular inheritance declared with the C<base> and C<parent> pragmata
=back
Since Perl does not allow you to supply a version requirement with a
C<require> statement, the scanner will check the statement after the
C<require Module> to see if it is C<< Module->VERSION( minimum_version ); >>.
In order to provide a minimum version, that method call must meet the
following requirements:
=over 4
=item *
it must be the very next statement after C<require Module>. Nothing can separate them but whitespace and comments (and one semicolon).
=item *
C<Module> must be a bareword, and match the C<require> exactly.
=item *
C<minimum_version> must be a literal number, v-string, or single-quoted string. Double quotes are not allowed.
=back
=head1 AUTHORS
=over 4
=item *
Jerome Quelin
=item *
Ricardo Signes <rjbs@cpan.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2009 by Jerome Quelin.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut