use strict; use warnings; package Perl::PrereqScanner::Scanner::Perl5; { $Perl::PrereqScanner::Scanner::Perl5::VERSION = '1.014'; } use Moose; with 'Perl::PrereqScanner::Scanner'; # 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.014 =head1 DESCRIPTION This scanner will look for the following indicators: =over 4 =item * plain lines beginning with C or C in your perl modules and scripts, including minimum perl version =item * regular inheritance declared with the C and C pragmata =back Since Perl does not allow you to supply a version requirement with a C statement, the scanner will check the statement after the C 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. Nothing can separate them but whitespace and comments (and one semicolon). =item * C must be a bareword, and match the C exactly. =item * C 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 =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