File Coverage

blib/lib/Perl/PrereqScanner/Scanner/Moose.pm
Criterion Covered Total %
statement 60 62 96.7
branch 31 34 91.1
condition 18 21 85.7
subroutine 4 4 100.0
pod 0 1 0.0
total 113 122 92.6


line stmt bran cond sub pod time code
1 2     2   14 use strict;
  2         5  
  2         57  
2 2     2   10 use warnings;
  2         4  
  2         69  
3              
4             package Perl::PrereqScanner::Scanner::Moose 1.100;
5             # ABSTRACT: scan for Moose sugar indicators of required modules
6              
7 2     2   11 use Moo;
  2         12  
  2         11  
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 * L inheritance declared with the C keyword
17             #pod
18             #pod * L roles included with the C keyword
19             #pod
20             #pod =end :list
21             #pod
22             #pod =cut
23              
24             sub scan_for_prereqs {
25 265     265 0 590 my ($self, $ppi_doc, $req) = @_;
26              
27             # Moose-based roles / inheritance
28             my @chunks =
29             # This is what we get when someone does: with('Foo');
30             # The target to get at is the PPI::Token::Quote::Single.
31             # -- rjbs, 2010-09-05
32             #
33             # PPI::Statement
34             # PPI::Token::Word
35             # PPI::Structure::List
36             # PPI::Statement::Expression
37             # PPI::Token::Quote::Single
38             # PPI::Token::Structure
39              
40 132         2392 map { [ $_->schildren ] }
41 489         6129 grep { $_->child(0)->literal =~ m{\A(?:with|extends)\z} }
42 616         170085 grep { $_->child(0)->isa('PPI::Token::Word') }
43 265 100       451 @{ $ppi_doc->find('PPI::Statement') || [] };
  265         637  
44              
45 265         5059 foreach my $hunk ( @chunks ) {
46             # roles/inheritance *WITH* version declaration ( added in Moose 1.03 )
47 132 100       420 if ( grep { $_->isa('PPI::Structure::Constructor') || $_->isa('PPI::Structure::List') } @$hunk ) {
  528 100       3343  
48             # hack for List
49 96         224 my @hunkdata = @$hunk;
50 96         379 while ( $hunkdata[0]->isa('PPI::Token::Whitespace') ) { shift @hunkdata }
  0         0  
51 96 100       263 if ( $hunkdata[1]->isa('PPI::Structure::List') ) {
52 60         431 @hunkdata = $hunkdata[1]->children;
53 60 50       419 next unless @hunkdata;
54 60         200 while ( $hunkdata[0]->isa('PPI::Token::Whitespace') ) { shift @hunkdata }
  42         141  
55             }
56 96 100       291 if ( $hunkdata[0]->isa('PPI::Statement::Expression') ) {
57 60         148 @hunkdata = $hunkdata[0]->children;
58 60 50       346 next unless @hunkdata;
59             }
60              
61             # possibly contains a version declaration!
62 96         181 my( $pkg, $done );
63 96         203 foreach my $elem ( @hunkdata ) {
64             # Scan for the first quote-like word, which is the package name
65 672 100 66     2760 if ( $elem->isa('PPI::Token::Quote') || $elem->isa('PPI::Token::QuoteLike') ) {
66             # found a new package and the previous one didn't have a version?
67 180 100       386 if ( defined $pkg ) {
68 36         106 $req->add_minimum( $pkg => 0 );
69             }
70 180         1799 $pkg = ( $self->_q_contents( $elem ) )[0];
71 180         331 undef $done;
72 180         348 next;
73             }
74              
75             # skip over the fluff and look for the version block
76 492 100 100     1575 if ( $pkg and $elem->isa('PPI::Structure::Constructor') ) {
77 87         218 foreach my $subelem ( $elem->children ) {
78             # skip over the fluff and look for the real version code
79 234 100       1096 if ( $subelem->isa('PPI::Statement') ) {
80 87         131 my $found_ver;
81 87         186 foreach my $code ( $subelem->children ) {
82             # skip over the fluff until we're sure we saw the version declaration
83 468 100 100     1743 if ( $code->isa('PPI::Token::Word') and $code->literal eq '-version' ) {
84 81         1295 $found_ver++;
85 81         168 next;
86             }
87              
88 387 100 100     2126 if ( $found_ver and ( $code->isa('PPI::Token::Quote') || $code->isa('PPI::Token::QuoteLike') || $code->isa('PPI::Token::Number') ) ) {
      100        
89 81         225 $req->add_minimum( $pkg => ( $self->_q_contents( $code ) )[0] );
90 81         7312 $done++;
91 81         167 undef $pkg;
92 81         153 last;
93             }
94             }
95              
96             # Did we fail to find the ver?
97 87 50 66     368 if ( $found_ver and ! $done ) {
98 0         0 die "Possible internal error!";
99             }
100             }
101             }
102              
103             # Failed to find version-specific stuff
104 87 100       259 if ( ! $done ) {
105 6         23 $req->add_minimum( $pkg => 0 );
106 6         211 undef $pkg;
107 6         15 next;
108             }
109             }
110             }
111              
112             # If we found a pkg but no done, this must be the "last" pkg to be declared and it has no version
113 96 100 66     417 if ( $pkg and ! $done ) {
114 57         162 $req->add_minimum( $pkg => 0 );
115             }
116             } else {
117             # no version or funky blocks in code, yay!
118 36         72 $req->add_minimum( $_ => 0 ) for
119 42         202 grep { Params::Util::_CLASS($_) }
120 36         126 map { $self->_q_contents( $_ ) }
121 114 100       541 grep { $_->isa('PPI::Token::Quote') || $_->isa('PPI::Token::QuoteLike') }
122             @$hunk;
123             }
124             }
125             }
126              
127             1;
128              
129             __END__