File Coverage

blib/lib/Perl/PrereqScanner.pm
Criterion Covered Total %
statement 71 72 98.6
branch 9 16 56.2
condition n/a
subroutine 20 20 100.0
pod 4 5 80.0
total 104 113 92.0


line stmt bran cond sub pod time code
1 3     3   48387 use 5.008;
  3         29  
2 3     3   16 use strict;
  3         6  
  3         69  
3 3     3   17 use warnings;
  3         6  
  3         174  
4              
5             package Perl::PrereqScanner 1.100;
6             # ABSTRACT: a tool to scan your Perl code for its prerequisites
7              
8 3     3   1595 use Moo 2.000000;
  3         37838  
  3         17  
9              
10 3     3   4297 use Carp qw(confess);
  3         8  
  3         133  
11 3     3   16 use List::Util qw(max);
  3         7  
  3         328  
12 3     3   1462 use Params::Util qw(_CLASS);
  3         13084  
  3         185  
13 3     3   1212 use Perl::PrereqScanner::Scanner;
  3         9  
  3         98  
14 3     3   1514 use PPI 1.215; # module_version, bug fixes
  3         310503  
  3         174  
15 3         27 use String::RewritePrefix 0.005 rewrite => {
16             -as => '__rewrite_scanner',
17             prefixes => { '' => 'Perl::PrereqScanner::Scanner::', '=' => '' },
18 3     3   1253 };
  3         26142  
19 3     3   4208 use Types::Standard qw(ArrayRef ConsumerOf);
  3         225695  
  3         28  
20              
21 3     3   4617 use CPAN::Meta::Requirements 2.124; # normalized v-strings
  3         20770  
  3         93  
22              
23 3     3   1408 use namespace::autoclean;
  3         39772  
  3         13  
24              
25             has scanners => (
26             is => 'rwp',
27             isa => ArrayRef[ConsumerOf['Perl::PrereqScanner::Scanner']],
28             init_arg => undef,
29             );
30              
31             sub __scanner_from_str {
32 540     540   1484 my $class = __rewrite_scanner($_[0]);
33 540 50       14266 confess "illegal class name: $class" unless _CLASS($class);
34 540 50       32999 eval "require $class; 1" or die $@;
35 540         2750 return $class->new;
36             }
37              
38             sub __prepare_scanners {
39 90     90   191 my ($self, $specs) = @_;
40 90 50       191 my @scanners = map {; ref $_ ? $_ : __scanner_from_str($_) } @$specs;
  540         7281  
41              
42 90         1482 return \@scanners;
43             }
44              
45             sub BUILD {
46 90     90 0 80773 my ($self, $arg) = @_;
47              
48 90 50       208 my @scanners = @{ $arg->{scanners} || [ qw(Perl5 Superclass TestMore Moose Aliased POE) ] };
  90         633  
49 90 50       215 my @extra_scanners = @{ $arg->{extra_scanners} || [] };
  90         307  
50              
51 90         310 my $scanners = $self->__prepare_scanners([ @scanners, @extra_scanners ]);
52              
53 90         1836 $self->_set_scanners($scanners);
54             }
55              
56             #pod =method scan_string
57             #pod
58             #pod my $prereqs = $scanner->scan_string( $perl_code );
59             #pod
60             #pod Given a string containing Perl source code, this method returns a
61             #pod CPAN::Meta::Requirements object describing the modules it requires.
62             #pod
63             #pod This method will throw an exception if PPI fails to parse the code.
64             #pod
65             #pod B It isn't entirely clear whether PPI prefers to receive
66             #pod strings as octet strings or character strings. For now, my advice
67             #pod is to pass octet strings.
68             #pod
69             #pod =cut
70              
71             sub scan_string {
72 89     89 1 76413 my ($self, $str) = @_;
73 89         326 my $ppi = PPI::Document->new( \$str );
74 89 100       181881 confess "PPI parse failed: " . PPI::Document->errstr unless defined $ppi;
75              
76 88         252 return $self->scan_ppi_document( $ppi );
77             }
78              
79             #pod =method scan_file
80             #pod
81             #pod my $prereqs = $scanner->scan_file( $path );
82             #pod
83             #pod Given a file path to a Perl document, this method returns a
84             #pod CPAN::Meta::Requirements object describing the modules it requires.
85             #pod
86             #pod This method will throw an exception if PPI fails to parse the code.
87             #pod
88             #pod =cut
89              
90             sub scan_file {
91 89     89 1 114849 my ($self, $path) = @_;
92 89         587 my $ppi = PPI::Document->new( $path );
93 89 50       307726 confess "PPI failed to parse '$path': " . PPI::Document->errstr
94             unless defined $ppi;
95              
96 89         299 return $self->scan_ppi_document( $ppi );
97             }
98              
99             #pod =method scan_ppi_document
100             #pod
101             #pod my $prereqs = $scanner->scan_ppi_document( $ppi_doc );
102             #pod
103             #pod Given a L, this method returns a CPAN::Meta::Requirements object
104             #pod describing the modules it requires.
105             #pod
106             #pod =cut
107              
108             sub scan_ppi_document {
109 265     265 1 216214 my ($self, $ppi_doc) = @_;
110              
111 265         1083 my $req = CPAN::Meta::Requirements->new;
112              
113 265         4207 for my $scanner (@{ $self->{scanners} }) {
  265         671  
114 1590         29470 $scanner->scan_for_prereqs($ppi_doc, $req);
115             }
116              
117 265         4659 return $req;
118             }
119              
120             #pod =method scan_module
121             #pod
122             #pod my $prereqs = $scanner->scan_module( $module_name );
123             #pod
124             #pod Given the name of a module, eg C<'PPI::Document'>,
125             #pod this method returns a CPAN::Meta::Requirements object
126             #pod describing the modules it requires.
127             #pod
128             #pod =cut
129              
130             sub scan_module {
131 1     1 1 347 my ($self, $module_name) = @_;
132              
133             # consider rewriting to use Module::Which -- rjbs, 2013-11-03
134 1         480 require Module::Path;
135 1 50       636 if (defined(my $path = Module::Path::module_path($module_name))) {
136 1         180 return $self->scan_file($path);
137             }
138              
139 0           confess "Failed to find file for module '$module_name'";
140             }
141              
142             1;
143              
144             =pod
145              
146             =encoding UTF-8
147              
148             =head1 NAME
149              
150             Perl::PrereqScanner - a tool to scan your Perl code for its prerequisites
151              
152             =head1 VERSION
153              
154             version 1.100
155              
156             =head1 SYNOPSIS
157              
158             use Perl::PrereqScanner;
159             my $scanner = Perl::PrereqScanner->new;
160             my $prereqs = $scanner->scan_ppi_document( $ppi_doc );
161             my $prereqs = $scanner->scan_file( $file_path );
162             my $prereqs = $scanner->scan_string( $perl_code );
163             my $prereqs = $scanner->scan_module( $module_name );
164              
165             =head1 DESCRIPTION
166              
167             The scanner will extract loosely your distribution prerequisites from your
168             files.
169              
170             The extraction may not be perfect but tries to do its best. It will currently
171             find the following prereqs:
172              
173             =over 4
174              
175             =item *
176              
177             plain lines beginning with C or C in your perl modules and scripts, including minimum perl version
178              
179             =item *
180              
181             regular inheritance declared with the C and C pragmata
182              
183             =item *
184              
185             L inheritance declared with the C keyword
186              
187             =item *
188              
189             L roles included with the C keyword
190              
191             =item *
192              
193             OO namespace aliasing using the C module
194              
195             =back
196              
197             =head2 Scanner Plugins
198              
199             Perl::PrereqScanner works by running a series of scanners over a PPI::Document
200             representing the code to scan. By default the "Perl5", "Moose", "TestMore",
201             "POE", and "Aliased" scanners are run. You can supply your own scanners when
202             constructing your PrereqScanner:
203              
204             # Us only the Perl5 scanner:
205             my $scanner = Perl::PrereqScanner->new({ scanners => [ qw(Perl5) ] });
206              
207             # Use any stock scanners, plus Example:
208             my $scanner = Perl::PrereqScanner->new({ extra_scanners => [ qw(Example) ] });
209              
210             =head1 PERL VERSION
211              
212             This library should run on perls released even a long time ago. It should work
213             on any version of perl released in the last five years.
214              
215             Although it may work on older versions of perl, no guarantee is made that the
216             minimum required version will not be increased. The version may be increased
217             for any reason, and there is no promise that patches will be accepted to lower
218             the minimum required perl.
219              
220             =head1 METHODS
221              
222             =head2 scan_string
223              
224             my $prereqs = $scanner->scan_string( $perl_code );
225              
226             Given a string containing Perl source code, this method returns a
227             CPAN::Meta::Requirements object describing the modules it requires.
228              
229             This method will throw an exception if PPI fails to parse the code.
230              
231             B It isn't entirely clear whether PPI prefers to receive
232             strings as octet strings or character strings. For now, my advice
233             is to pass octet strings.
234              
235             =head2 scan_file
236              
237             my $prereqs = $scanner->scan_file( $path );
238              
239             Given a file path to a Perl document, this method returns a
240             CPAN::Meta::Requirements object describing the modules it requires.
241              
242             This method will throw an exception if PPI fails to parse the code.
243              
244             =head2 scan_ppi_document
245              
246             my $prereqs = $scanner->scan_ppi_document( $ppi_doc );
247              
248             Given a L, this method returns a CPAN::Meta::Requirements object
249             describing the modules it requires.
250              
251             =head2 scan_module
252              
253             my $prereqs = $scanner->scan_module( $module_name );
254              
255             Given the name of a module, eg C<'PPI::Document'>,
256             this method returns a CPAN::Meta::Requirements object
257             describing the modules it requires.
258              
259             =for Pod::Coverage::TrustPod new
260              
261             =head1 SEE ALSO
262              
263             L, in this distribution, is a command-line interface to the scanner
264              
265             =head1 AUTHORS
266              
267             =over 4
268              
269             =item *
270              
271             Jerome Quelin
272              
273             =item *
274              
275             Ricardo Signes
276              
277             =back
278              
279             =head1 CONTRIBUTORS
280              
281             =for stopwords bowtie celogeek Christopher J. Madsen Dan Book David Golden Steinbrunner Ed J Florian Ragwitz Jakob Voss Jérôme Quelin John SJ Anderson Karen Etheridge Mark Gardner Neil Bowers Randy Stauner Ricardo Signes Tina Mueller Vyacheslav Matjukhin
282              
283             =over 4
284              
285             =item *
286              
287             bowtie
288              
289             =item *
290              
291             celogeek
292              
293             =item *
294              
295             Christopher J. Madsen
296              
297             =item *
298              
299             Dan Book
300              
301             =item *
302              
303             David Golden
304              
305             =item *
306              
307             David Steinbrunner
308              
309             =item *
310              
311             Ed J
312              
313             =item *
314              
315             Florian Ragwitz
316              
317             =item *
318              
319             Jakob Voss
320              
321             =item *
322              
323             Jérôme Quelin
324              
325             =item *
326              
327             John SJ Anderson
328              
329             =item *
330              
331             Karen Etheridge
332              
333             =item *
334              
335             Mark Gardner
336              
337             =item *
338              
339             Neil Bowers
340              
341             =item *
342              
343             Randy Stauner
344              
345             =item *
346              
347             Ricardo Signes
348              
349             =item *
350              
351             Tina Mueller
352              
353             =item *
354              
355             Vyacheslav Matjukhin
356              
357             =back
358              
359             =head1 COPYRIGHT AND LICENSE
360              
361             This software is copyright (c) 2009 by Jerome Quelin.
362              
363             This is free software; you can redistribute it and/or modify it under
364             the same terms as the Perl 5 programming language system itself.
365              
366             =cut
367              
368             __END__