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   13 use strict;
  2         4  
  2         61  
2 2     2   9 use warnings;
  2         4  
  2         81  
3              
4             package Perl::PrereqScanner::Scanner::Moose 1.024;
5             # ABSTRACT: scan for Moose sugar indicators of required modules
6              
7 2     2   9 use Moose;
  2         4  
  2         19  
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<Moose> inheritance declared with the C<extends> keyword
17             #pod
18             #pod * L<Moose> roles included with the C<with> keyword
19             #pod
20             #pod =end :list
21             #pod
22             #pod =cut
23              
24             sub scan_for_prereqs {
25 265     265 0 871 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         2568 map { [ $_->schildren ] }
41 486         6391 grep { $_->child(0)->literal =~ m{\A(?:with|extends)\z} }
42 612         142486 grep { $_->child(0)->isa('PPI::Token::Word') }
43 265 100       633 @{ $ppi_doc->find('PPI::Statement') || [] };
  265         878  
44              
45 265         5840 foreach my $hunk ( @chunks ) {
46             # roles/inheritance *WITH* version declaration ( added in Moose 1.03 )
47 132 100       550 if ( grep { $_->isa('PPI::Structure::Constructor') || $_->isa('PPI::Structure::List') } @$hunk ) {
  528 100       3489  
48             # hack for List
49 96         310 my @hunkdata = @$hunk;
50 96         679 while ( $hunkdata[0]->isa('PPI::Token::Whitespace') ) { shift @hunkdata }
  0         0  
51 96 100       372 if ( $hunkdata[1]->isa('PPI::Structure::List') ) {
52 60         567 @hunkdata = $hunkdata[1]->children;
53 60 50       455 next unless @hunkdata;
54 60         271 while ( $hunkdata[0]->isa('PPI::Token::Whitespace') ) { shift @hunkdata }
  42         142  
55             }
56 96 100       447 if ( $hunkdata[0]->isa('PPI::Statement::Expression') ) {
57 60         163 @hunkdata = $hunkdata[0]->children;
58 60 50       383 next unless @hunkdata;
59             }
60              
61             # possibly contains a version declaration!
62 96         242 my( $pkg, $done );
63 96         350 foreach my $elem ( @hunkdata ) {
64             # Scan for the first quote-like word, which is the package name
65 672 100 66     2698 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       391 if ( defined $pkg ) {
68 36         159 $req->add_minimum( $pkg => 0 );
69             }
70 180         2636 $pkg = ( $self->_q_contents( $elem ) )[0];
71 180         327 undef $done;
72 180         380 next;
73             }
74              
75             # skip over the fluff and look for the version block
76 492 100 100     1542 if ( $pkg and $elem->isa('PPI::Structure::Constructor') ) {
77 87         328 foreach my $subelem ( $elem->children ) {
78             # skip over the fluff and look for the real version code
79 234 100       1091 if ( $subelem->isa('PPI::Statement') ) {
80 87         117 my $found_ver;
81 87         214 foreach my $code ( $subelem->children ) {
82             # skip over the fluff until we're sure we saw the version declaration
83 468 100 100     1694 if ( $code->isa('PPI::Token::Word') and $code->literal eq '-version' ) {
84 81         919 $found_ver++;
85 81         161 next;
86             }
87              
88 387 100 100     2163 if ( $found_ver and ( $code->isa('PPI::Token::Quote') || $code->isa('PPI::Token::QuoteLike') || $code->isa('PPI::Token::Number') ) ) {
      100        
89 81         209 $req->add_minimum( $pkg => ( $self->_q_contents( $code ) )[0] );
90 81         9276 $done++;
91 81         158 undef $pkg;
92 81         130 last;
93             }
94             }
95              
96             # Did we fail to find the ver?
97 87 50 66     452 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       277 if ( ! $done ) {
105 6         24 $req->add_minimum( $pkg => 0 );
106 6         262 undef $pkg;
107 6         13 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     572 if ( $pkg and ! $done ) {
114 57         214 $req->add_minimum( $pkg => 0 );
115             }
116             } else {
117             # no version or funky blocks in code, yay!
118 36         115 $req->add_minimum( $_ => 0 ) for
119 42         203 grep { Params::Util::_CLASS($_) }
120 36         171 map { $self->_q_contents( $_ ) }
121 114 100       631 grep { $_->isa('PPI::Token::Quote') || $_->isa('PPI::Token::QuoteLike') }
122             @$hunk;
123             }
124             }
125             }
126              
127             1;
128              
129             __END__
130              
131             =pod
132              
133             =encoding UTF-8
134              
135             =head1 NAME
136              
137             Perl::PrereqScanner::Scanner::Moose - scan for Moose sugar indicators of required modules
138              
139             =head1 VERSION
140              
141             version 1.024
142              
143             =head1 DESCRIPTION
144              
145             This scanner will look for the following indicators:
146              
147             =over 4
148              
149             =item *
150              
151             L<Moose> inheritance declared with the C<extends> keyword
152              
153             =item *
154              
155             L<Moose> roles included with the C<with> keyword
156              
157             =back
158              
159             =head1 PERL VERSION
160              
161             This library should run on perls released even a long time ago. It should work
162             on any version of perl released in the last five years.
163              
164             Although it may work on older versions of perl, no guarantee is made that the
165             minimum required version will not be increased. The version may be increased
166             for any reason, and there is no promise that patches will be accepted to lower
167             the minimum required perl.
168              
169             =head1 AUTHORS
170              
171             =over 4
172              
173             =item *
174              
175             Jerome Quelin
176              
177             =item *
178              
179             Ricardo Signes <rjbs@semiotic.systems>
180              
181             =back
182              
183             =head1 COPYRIGHT AND LICENSE
184              
185             This software is copyright (c) 2009 by Jerome Quelin.
186              
187             This is free software; you can redistribute it and/or modify it under
188             the same terms as the Perl 5 programming language system itself.
189              
190             =cut