File Coverage

blib/lib/Perl/PrereqScanner/Scanner/Perl5.pm
Criterion Covered Total %
statement 37 38 97.3
branch 20 22 90.9
condition 32 43 74.4
subroutine 5 5 100.0
pod 0 1 0.0
total 94 109 86.2


line stmt bran cond sub pod time code
1 2     2   14 use strict;
  2         4  
  2         58  
2 2     2   11 use warnings;
  2         4  
  2         70  
3              
4             package Perl::PrereqScanner::Scanner::Perl5 1.100;
5             # ABSTRACT: scan for core Perl 5 language indicators of required modules
6              
7 2     2   10 use Moo;
  2         4  
  2         12  
8             with 'Perl::PrereqScanner::Scanner';
9              
10             #pod =head1 DESCRIPTION
11             #pod
12             #pod This scanner will look for the following indicators:
13             #pod
14             #pod =begin :list
15             #pod
16             #pod * plain lines beginning with C, C, or C in your perl modules and scripts, including minimum perl version
17             #pod
18             #pod * regular inheritance declared with the C and C pragmata
19             #pod
20             #pod =end :list
21             #pod
22             #pod Since Perl does not allow you to supply a version requirement with a
23             #pod C statement, the scanner will check the statement after the
24             #pod C to see if it is C<< Module->VERSION( minimum_version ); >>.
25             #pod
26             #pod In order to provide a minimum version, that method call must meet the
27             #pod following requirements:
28             #pod
29             #pod =begin :list
30             #pod
31             #pod * it must be the very next statement after C. Nothing can separate them but whitespace and comments (and one semicolon).
32             #pod
33             #pod * C must be a bareword, and match the C exactly.
34             #pod
35             #pod * C must be a literal number, v-string, or single-quoted string. Double quotes are not allowed.
36             #pod
37             #pod =end :list
38             #pod
39             #pod =cut
40              
41             sub scan_for_prereqs {
42 265     265 0 573 my ($self, $ppi_doc, $req) = @_;
43              
44             # regular use, require, and no
45 265   100     753 my $includes = $ppi_doc->find('Statement::Include') || [];
46 265         173142 for my $node ( @$includes ) {
47             # minimum perl version
48 173 100       3776 if ( $node->version ) {
49 1         35 $req->add_minimum(perl => $node->version);
50 1         169 next;
51             }
52              
53             # inheritance
54 172 100       4625 if (grep { $_ eq $node->module } qw{ base parent }) {
  344         4705  
55             # rt#55713: skip arguments to base or parent, focus only on inheritance
56             my @meat = grep {
57 33 100       815 $_->isa('PPI::Token::QuoteLike::Words')
  39         1357  
58             || $_->isa('PPI::Token::Quote')
59             } $node->arguments;
60              
61 33         74 my @parents = map { $self->_q_contents($_) } @meat;
  33         108  
62 33         127 $req->add_minimum($_ => 0) for @parents;
63             }
64              
65             # regular modules
66 172 100       5266 my $version = $node->module_version ? $node->module_version->content : 0;
67              
68             # rt#55851: 'require $foo;' shouldn't add any prereq
69 172 100       10591 next unless $node->module;
70              
71             # See if the next statement after require is Module->VERSION(min):
72 169 100 100     4129 $version = $self->_check_required_version($node) || 0
      100        
73             if not $version and $node->type =~ /\A(?:require|use)\z/;
74              
75 169         992 $req->add_minimum($node->module, $version);
76             }
77             }
78              
79             # For "require Module", see if the next statement is Module->VERSION(min):
80             sub _check_required_version {
81 108     108   2795 my ($self, $node) = @_;
82              
83 108         314 my $next = $node->snext_sibling;
84              
85 108 100 100     3257 return unless $next and $next->class eq 'PPI::Statement';
86              
87 34         243 my ($invocant, $op, $method, $list, $too_much) = $next->schildren;
88              
89 34 50 100     571 return unless defined $list # need enough children
      66        
      66        
      66        
      66        
      100        
      66        
      66        
      33        
90             and $op->class eq 'PPI::Token::Operator'
91             and $op->content eq '->'
92             and $method->content eq 'VERSION'
93             and (not defined $too_much # but not too many children
94             or $too_much->content eq ';')
95             and $invocant->content eq $node->module
96             and $list->class eq 'PPI::Structure::List'
97             and $list->braces eq '()'
98             and $list->schildren == 1;
99              
100 21         1504 my $exp = $list->schild(0);
101              
102 21 100 66     258 return unless $exp->class eq 'PPI::Statement::Expression'
103             and $exp->schildren == 1;
104              
105 18         269 my $arg = $exp->schild(0);
106              
107 18 100 33     273 if ($arg->isa('PPI::Token::Number')) {
    50          
108 12         38 return $arg->content;
109             } elsif ($arg->isa('PPI::Token::Quote') and $arg->can('literal')) {
110 6         24 return $arg->literal;
111             }
112              
113 0           return; # No minimum version found
114             } # end _check_required_version
115              
116             1;
117              
118             __END__