File Coverage

blib/lib/Perl/MinimumVersion.pm
Criterion Covered Total %
statement 510 554 92.0
branch 352 476 73.9
condition 141 198 71.2
subroutine 127 134 94.7
pod 7 12 58.3
total 1137 1374 82.7


line stmt bran cond sub pod time code
1             package Perl::MinimumVersion;
2             $Perl::MinimumVersion::VERSION = '1.40';
3             =pod
4              
5             =head1 NAME
6              
7             Perl::MinimumVersion - Find a minimum required version of perl for Perl code
8              
9             =head1 SYNOPSIS
10              
11             # Create the version checking object
12             $object = Perl::MinimumVersion->new( $filename );
13             $object = Perl::MinimumVersion->new( \$source );
14             $object = Perl::MinimumVersion->new( $ppi_document );
15              
16             # Find the minimum version
17             $version = $object->minimum_version;
18              
19             =head1 DESCRIPTION
20              
21             C takes Perl source code and calculates the minimum
22             version of perl required to be able to run it. Because it is based on
23             L, it can do this without having to actually load the code.
24              
25             Currently it tests both the syntax of your code, and the use of explicit
26             version dependencies such as C.
27              
28             Future plans are to also add support for tracing module dependencies.
29              
30             Using C is dead simple, the synopsis pretty much
31             covers it.
32              
33             The distribution comes with a script called L,
34             which is the easiest way to run C on your code:
35              
36             % perlver lib/Foo/Bar.pm
37              
38             See the L for more details.
39              
40             =head1 METHODS
41              
42             =cut
43              
44 26     26   1935928 use 5.006;
  26         388  
45 26     26   149 use strict;
  26         49  
  26         827  
46 26     26   173 use warnings;
  26         90  
  26         1240  
47 26     26   12007 use version 0.76 ();
  26         49323  
  26         796  
48 26     26   185 use Carp ();
  26         53  
  26         360  
49 26     26   119 use Exporter ();
  26         52  
  26         726  
50 26     26   145 use List::Util 1.20 qw(max first);
  26         450  
  26         3333  
51 26     26   12989 use Params::Util 0.25 ('_INSTANCE', '_CLASS');
  26         162693  
  26         1893  
52 26     26   11980 use PPI::Util ('_Document');
  26         19100  
  26         1604  
53 26     26   13399 use PPI 1.215 ();
  26         2680117  
  26         1477  
54 26         6229 use PPIx::Utils qw{
55             :classification
56             :traversal
57 26     26   12539 };
  26         387744  
58 26     26   17057 use PPIx::Regexp 0.033;
  26         3187643  
  26         1014  
59 26     26   13930 use Perl::MinimumVersion::Reason ();
  26         75  
  26         10416  
60              
61             our (@ISA, @EXPORT_OK, %CHECKS, @CHECKS_RV ,%MATCHES);
62             BEGIN {
63             # Export the PMV convenience constant
64 26     26   634 @ISA = 'Exporter';
65 26         121 @EXPORT_OK = 'PMV';
66              
67             # The primary list of version checks
68 26         3905 %CHECKS = (
69             # _stacked_labels => version->new('5.014'),
70              
71             _yada_yada_yada => version->new('5.012'),
72             _pkg_name_version => version->new('5.012'),
73             _postfix_when => version->new('5.012'),
74             _perl_5012_pragmas => version->new('5.012'),
75             _while_readdir => version->new('5.012'),
76              
77             _perl_5010_pragmas => version->new('5.010'),
78             _perl_5010_operators => version->new('5.010'),
79             _perl_5010_magic => version->new('5.010'),
80             _state_declaration => version->new('5.010'),
81              
82             # Various small things
83             _bugfix_magic_errno => version->new('5.008.003'),
84             _is_utf8 => version->new('5.008.001'),
85             _unquoted_versions => version->new('5.008.001'),
86             _perl_5008_pragmas => version->new('5.008'),
87             _constant_hash => version->new('5.008'),
88             _local_soft_reference => version->new('5.008'),
89             _use_carp_version => version->new('5.008'),
90             _open_temp => version->new('5.008'),
91             _open_scalar => version->new('5.008'),
92             _internals_svreadonly => version->new('5.008'),
93              
94             # Included in 5.6. Broken until 5.8
95             _pragma_utf8 => version->new('5.008'),
96              
97             _perl_5006_pragmas => version->new('5.006'),
98             _any_our_variables => version->new('5.006'),
99             _any_binary_literals => version->new('5.006'),
100             _any_version_literals => version->new('5.006'), #v-string
101             _magic_version => version->new('5.006'),
102             _any_attributes => version->new('5.006'),
103             _any_CHECK_blocks => version->new('5.006'),
104             _three_argument_open => version->new('5.006'),
105             _weaken => version->new('5.006'),
106             _mkdir_1_arg => version->new('5.006'),
107             _exists_subr => version->new('5.006'),
108             _sort_subref => version->new('5.006'),
109              
110             _any_qr_tokens => version->new('5.005.03'),
111             _perl_5005_pragmas => version->new('5.005'),
112             _perl_5005_modules => version->new('5.005'),
113             _any_tied_arrays => version->new('5.005'),
114             _any_quotelike_regexp => version->new('5.005'),
115             _any_INIT_blocks => version->new('5.005'),
116             _substr_4_arg => version->new('5.005'),
117             _splice_negative_length => version->new('5.005'),
118             _5005_variables => version->new('5.005'),
119             _bareword_double_colon => version->new('5.005'),
120              
121             _postfix_foreach => version->new('5.004.05'),
122             );
123 26         160 @CHECKS_RV = ( #subs that return version
124             '_feature_bundle','_regex','_each_argument','_binmode_2_arg',
125             '_scheduled_blocks', '_experimental_bundle'
126             );
127              
128             # Predefine some indexes needed by various check methods
129 26         213950 %MATCHES = (
130             _perl_5012_pragmas => {
131             deprecate => 1,
132             },
133             _perl_5010_pragmas => {
134             mro => 1,
135             feature => 1,
136             },
137             _perl_5010_operators => {
138             '//' => 1,
139             '//=' => 1,
140             '~~' => 1,
141             },
142             _perl_5010_magic => {
143             '%+' => 1,
144             '%-' => 1,
145             },
146             _perl_5008_pragmas => {
147             threads => 1,
148             'threads::shared' => 1,
149             sort => 1,
150             encoding => 1,
151             },
152             _perl_5006_pragmas => {
153             warnings => 1, #may be ported into older version
154             'warnings::register' => 1,
155             attributes => 1,
156             open => 1,
157             filetest => 1,
158             charnames => 1,
159             bytes => 1,
160             },
161             _perl_5005_pragmas => {
162             re => 1,
163             fields => 1, # can be installed from CPAN, with base.pm
164             attr => 1,
165             },
166             );
167             }
168              
169             sub PMV () { 'Perl::MinimumVersion' }
170              
171              
172              
173              
174              
175             #####################################################################
176             # Constructor
177              
178             =pod
179              
180             =head2 new
181              
182             # Create the version checking object
183             $object = Perl::MinimumVersion->new( $filename );
184             $object = Perl::MinimumVersion->new( \$source );
185             $object = Perl::MinimumVersion->new( $ppi_document );
186              
187             The C constructor creates a new version checking object for a
188             L. You can also provide the document to be read as a
189             file name, or as a C reference containing the code.
190              
191             Returns a new C object, or C on error.
192              
193             =cut
194              
195             sub new {
196 260 50   260 1 265779 my $class = ref $_[0] ? ref shift : shift;
197 260 100       1052 my $Document = _Document(shift) or return undef;
198 257   33     690749 my $default = _INSTANCE(shift, 'version') || version->new('5.004');
199              
200             # Create the object
201 257         1921 my $self = bless {
202             Document => $Document,
203              
204             # Checking limit and default minimum version.
205             # Explicitly don't check below this version.
206             default => $default,
207              
208             # Caches for resolved versions
209             explicit => undef,
210             syntax => undef,
211             external => undef,
212             }, $class;
213              
214 257         890 $self;
215             }
216              
217             =pod
218              
219             =head2 Document
220              
221             The C accessor can be used to get the L object
222             back out of the version checker.
223              
224             =cut
225              
226             sub Document {
227             $_[0]->{Document}
228 1602     1602 1 9631 }
229              
230              
231              
232              
233              
234             #####################################################################
235             # Main Methods
236              
237             =pod
238              
239             =head2 minimum_version
240              
241             The C method is the primary method for finding the
242             minimum perl version required based on C factors in the document.
243              
244             At the present time, this is just syntax and explicit version checks,
245             as L is not yet completed.
246              
247             Returns a L object, or C on error.
248              
249             =cut
250              
251             sub minimum_version {
252 42 50   42 1 8840 my $self = _SELF(\@_) or return undef;
253 42         91 my $minimum = $self->{default}; # Sensible default
254              
255             # Is the explicit version greater?
256 42         110 my $explicit = $self->minimum_explicit_version;
257 42 50       119 return undef unless defined $explicit;
258 42 100 66     141 if ( $explicit and $explicit > $minimum ) {
259 2         5 $minimum = $explicit;
260             }
261              
262             # Is the syntax version greater?
263             # Since this is the most expensive operation (for this file),
264             # we need to be careful we don't run things we don't need to.
265 42         114 my $syntax = $self->minimum_syntax_version;
266 42 50       133 return undef unless defined $syntax;
267 42 100 100     451 if ( $syntax and $syntax > $minimum ) {
268 30         67 $minimum = $syntax;
269             }
270              
271             ### FIXME - Disabled until minimum_external_version completed
272             # Is the external version greater?
273             #my $external = $self->minimum_external_version;
274             #return undef unless defined $external;
275             #if ( $external and $external > $minimum ) {
276             # $minimum = $external;
277             #}
278              
279 42         187 $minimum;
280             }
281              
282             sub minimum_reason {
283 0 0   0 0 0 my $self = _SELF(\@_) or return undef;
284 0         0 my $minimum = $self->default_reason; # Sensible default
285              
286             # Is the explicit version greater?
287 0         0 my $explicit = $self->minimum_explicit_version;
288 0 0       0 return undef unless defined $explicit;
289 0 0 0     0 if ( $explicit and $explicit > $minimum ) {
290 0         0 $minimum = $explicit;
291             }
292              
293             }
294              
295             sub default_reason {
296             Perl::MinimumVersion::Reason->new(
297             rule => 'default',
298             version => $_[0]->{default},
299 0     0 0 0 element => undef,
300             );
301             }
302              
303             =pod
304              
305             =head2 minimum_explicit_version
306              
307             The C method checks through Perl code for the
308             use of explicit version dependencies such as.
309              
310             use 5.006;
311             require 5.005_03;
312              
313             Although there is almost always only one of these in a file, if more than
314             one are found, the highest version dependency will be returned.
315              
316             Returns a L object, false if no dependencies could be found,
317             or C on error.
318              
319             =cut
320              
321             sub minimum_explicit_version {
322 43 50   43 1 99 my $self = _SELF(\@_) or return undef;
323 43         117 my $reason = $self->minimum_explicit_reason(@_);
324 43 100       122 return $reason ? $reason->version : $reason;
325             }
326              
327             sub minimum_explicit_reason {
328 43 50   43 0 98 my $self = _SELF(\@_) or return undef;
329 43 100       133 unless ( defined $self->{explicit} ) {
330 42         113 $self->{explicit} = $self->_minimum_explicit_version;
331             }
332 43         102 return $self->{explicit};
333             }
334              
335             sub _minimum_explicit_version {
336 42 50   42   99 my $self = shift or return undef;
337             my $explicit = $self->Document->find( sub {
338 505 100   505   6796 $_[1]->isa('PPI::Statement::Include') or return '';
339 16 100       60 $_[1]->version or return '';
340 4         158 1;
341 42         93 } );
342 42 100       640 return $explicit unless $explicit;
343              
344             # Find the highest version
345 3         8 my $max = undef;
346 3         7 my $element = undef;
347 3         9 foreach my $include ( @$explicit ) {
348 4         11 my $version = version->new($include->version);
349 4 50 66     123 if ( not $element or $version > $max ) {
350 4         9 $max = $version;
351 4         11 $element = $include;
352             }
353             }
354              
355 3         12 return Perl::MinimumVersion::Reason->new(
356             rule => 'explicit',
357             version => $max,
358             element => $element,
359             );
360             }
361              
362             =pod
363              
364             =head2 minimum_syntax_version $limit
365              
366             The C method will explicitly test only the
367             Document's syntax to determine it's minimum version, to the extent
368             that this is possible.
369              
370             It takes an optional parameter of a L object defining
371             the lowest known current value. For example, if it is already known
372             that it must be 5.006 or higher, then you can provide a param of
373             qv(5.006) and the method will not run any of the tests below this
374             version. This should provide dramatic speed improvements for
375             large and/or complex documents.
376              
377             The limitations of parsing Perl mean that this method may provide
378             artificially low results, but should not artificially high results.
379              
380             For example, if C returned 5.006, you can be
381             confident it will not run on anything lower, although there is a chance
382             that during actual execution it may use some untestable feature that
383             creates a dependency on a higher version.
384              
385             Returns a L object, false if no dependencies could be found,
386             or C on error.
387              
388             =cut
389              
390             sub minimum_syntax_version {
391 48 50   48 1 127 my $self = _SELF(\@_) or return undef;
392 48         144 my $reason = $self->minimum_syntax_reason(@_);
393 48 100       243 return $reason ? $reason->version : $reason;
394             }
395              
396             sub minimum_syntax_reason {
397 51 50   51 0 131 my $self = _SELF(\@_) or return undef;
398 51         103 my $limit = shift;
399 51 100 100     149 if ( defined $limit and not _INSTANCE($limit, 'version') ) {
400 1         15 $limit = version->new("$limit");
401             }
402 51 100       130 if ( defined $self->{syntax} ) {
403 5 100 100     22 if ( !defined($limit) or $self->{syntax}->version >= $limit ) {
404             # Previously discovered minimum is what they want
405 4         14 return $self->{syntax};
406             }
407              
408             # Rather than return a value BELOW their filter,
409             # which they would not be expecting, return false.
410 1         7 return '';
411             }
412              
413             # Look for the value
414 46         116 my $syntax = $self->_minimum_syntax_version( $limit );
415              
416             # If we found a value, it will be stable, cache it.
417             # If we did NOT, don't cache as subsequent runs without
418             # the filter may find a version.
419 46 100       128 if ( $syntax ) {
420 34         69 $self->{syntax} = $syntax;
421 34         87 return $self->{syntax};
422             }
423              
424 12         33 return '';
425             }
426              
427             #for Perl::Critic::Policy::Compatibility::PerlMinimumVersionAndWhy
428             sub _set_checks2skip {
429 1     1   7 my $self = shift;
430 1         3 my $list = shift;
431 1         4 $self->{_checks2skip} = $list;
432             }
433             sub _set_collect_all_reasons {
434 1     1   7 my $self = shift;
435 1         2 my $value = shift;
436 1 50       6 $value = 1 unless defined $value;
437 1         3 $self->{_collect_all_reasons} = $value;
438             }
439              
440             sub _minimum_syntax_version {
441 46     46   72 my $self = shift;
442 46   66     436 my $filter = shift || $self->{default};
443              
444 46         143 my %checks2skip;
445 46 100       82 @checks2skip{ @{ $self->{_checks2skip} || [] } } = ();
  46         193  
446              
447 46         110 my %rv_result;
448             my $current_reason;
449 46         115 foreach my $rule ( @CHECKS_RV ) {
450 276 100       608 next if exists $checks2skip{$rule};
451 275         776 my ($v, $obj) = $self->$rule();
452 275         1455 $v = version->new($v);
453 275 100       1506 if ( $v > $filter ) {
454 15         131 $current_reason = Perl::MinimumVersion::Reason->new(
455             rule => $rule,
456             version => $v,
457             element => _INSTANCE($obj, 'PPI::Element'),
458             );
459 15 100       54 if ($self->{_collect_all_reasons}) {
460 1         3 push @{ $self->{_all_reasons} }, $current_reason;
  1         48  
461             } else {
462 14         34 $filter = $v;
463             }
464             }
465             }
466              
467              
468             # Always check in descending version order.
469             # By doing it this way, the version of the first check that matches
470             # is also the version of the document as a whole.
471             my @rules = sort {
472 6293         13667 $CHECKS{$b} <=> $CHECKS{$a}
473             } grep {
474 46 100       353 not(exists $checks2skip{$_}) and $CHECKS{$_} > $filter
  1978         7714  
475             } keys %CHECKS;
476              
477 46         184 foreach my $rule ( @rules ) {
478 1024 100       32469 my $result = $self->$rule() or next;
479              
480             # Create the result object
481             my $reason = Perl::MinimumVersion::Reason->new(
482             rule => $rule,
483 24         2293 version => $CHECKS{$rule},
484             element => _INSTANCE($result, 'PPI::Element'),
485             );
486 24 100       73 if ($self->{_collect_all_reasons}) {
487 2         4 push @{ $self->{_all_reasons} }, $current_reason;
  2         9  
488             } else {
489 22         112 return $reason;
490             }
491              
492             }
493              
494             # Found nothing of interest
495 24   100     619 return $current_reason || '';
496             }
497              
498             =pod
499              
500             =head2 minimum_external_version
501              
502             B
503             an exception>
504              
505             The C examines code for dependencies on other
506             external files, and recursively traverses the dependency tree applying the
507             same tests to those files as it does to the original.
508              
509             Returns a C object, false if no dependencies could be found, or
510             C on error.
511              
512             =cut
513              
514             sub minimum_external_version {
515 0 0   0 1 0 my $self = _SELF(\@_) or return undef;
516 0         0 my $reason = $self->minimum_explicit_reason(@_);
517 0 0       0 return $reason ? $reason->version : $reason;
518             }
519              
520             sub minimum_external_reason {
521 0 0   0 0 0 my $self = _SELF(\@_) or return undef;
522 0 0       0 unless ( defined $self->{external} ) {
523 0         0 $self->{external} = $self->_minimum_external_version;
524             }
525 0         0 $self->{external};
526             }
527              
528             sub _minimum_external_version {
529 0     0   0 Carp::croak("Perl::MinimumVersion::minimum_external_version is not implemented");
530             }
531              
532             =pod
533              
534             =head2 version_markers
535              
536             This method returns a list of pairs in the form:
537              
538             ($version, \@markers)
539              
540             Each pair represents all the markers that could be found indicating that the
541             version was the minimum needed version. C<@markers> is an array of strings.
542             Currently, these strings are not as clear as they might be, but this may be
543             changed in the future. In other words: don't rely on them as specific
544             identifiers.
545              
546             =cut
547              
548             sub version_markers {
549 1 50   1 1 698 my $self = _SELF(\@_) or return undef;
550              
551 1         3 my %markers;
552              
553 1 50       5 if ( my $explicit = $self->minimum_explicit_version ) {
554 1         7 $markers{ $explicit } = [ 'explicit' ];
555             }
556              
557 1         11 foreach my $check ( keys %CHECKS ) {
558 43 100       2535 next unless $self->$check();
559 3   100     911 my $markers = $markers{ $CHECKS{$check} } ||= [];
560 3         10 push @$markers, $check;
561             }
562              
563 1         18 my @rv;
564 1         5 my %marker_ver = map { $_ => version->new($_) } keys %markers;
  3         22  
565              
566 1         7 foreach my $ver ( sort { $marker_ver{$b} <=> $marker_ver{$a} } keys %markers ) {
  2         12  
567 3         8 push @rv, $marker_ver{$ver} => $markers{$ver};
568             }
569              
570 1         10 return @rv;
571             }
572              
573              
574              
575              
576             #####################################################################
577             # Version Check Methods
578              
579             my %feature =
580             (
581             'say' => '5.10',
582             'smartmatch' => '5.10',
583             'state' => '5.10',
584             'switch' => '5.10',
585             'unicode_strings' => '5.14',
586             'unicode_eval' => '5.16',
587             'evalbytes' => '5.16',
588             'current_sub' => '5.16',
589             'array_base' => '5.16', #defined only in 5.16
590             'fc' => '5.16',
591             'lexical_subs' => '5.18',
592             'postderef' => '5.20',
593             'postderef_qq' => '5.20',
594             'signatures' => '5.20',
595             'refaliasing' => '5.22',
596             'bitwise' => '5.22',
597             'declared_refs' => '5.26',
598             'isa' => '5.32',
599             'indirect' => '5.32', #defined only in 5.32
600             );
601             my $feature_regexp = join('|', keys %feature);
602              
603             #:5.14 means same as :5.12, but :5.14 is not defined in feature.pm in perl 5.12.
604             sub _feature_bundle {
605 70     70   156 my @versions;
606 70         123 my ($version, $obj);
607             shift->Document->find( sub {
608 688 100   688   8645 $_[1]->isa('PPI::Statement::Include') or return '';
609 40 100       130 $_[1]->pragma eq 'feature' or return '';
610 31         1199 my @child = $_[1]->schildren;
611 31         499 my @args = @child[1..$#child]; # skip 'use', 'feature' and ';'
612 31         74 foreach my $arg (@args) {
613 92         134 my $v = 0;
614 92 100       184 $v = $1 if ($arg->content =~ /:(5\.\d+)(?:\.\d+)?/);
615 92 100       514 $v = max($v, $feature{$1}) if ($arg->content =~ /\b($feature_regexp)\b/);
616             #
617 92 100 100     1140 if ($v and $v > ($version || 0) ) {
      100        
618 29         55 $version = $v;
619 29         65 $obj = $_[1];
620             }
621             }
622 31         81 return '';
623 70         166 } );
624 70 100       1318 return (defined($version)?"$version.0":undef, $obj);
625             }
626              
627             # list copied from experimental.pm v0.021 itself
628             my %experimental =
629             (
630             array_base => '5',
631             autoderef => '5.14',
632             bitwise => '5.22',
633             const_attr => '5.22',
634             current_sub => '5.16',
635             declared_refs => '5.26',
636             evalbytes => '5.16',
637             fc => '5.16',
638             isa => '5.32',
639             lexical_topic => '5.10',
640             lexical_subs => '5.18',
641             postderef => '5.20',
642             postderef_qq => '5.20',
643             refaliasing => '5.22',
644             regex_sets => '5.18',
645             say => '5.10',
646             smartmatch => '5.10',
647             signatures => '5.20',
648             state => '5.10',
649             switch => '5.10',
650             unicode_eval => '5.16',
651             unicode_strings => '5.12',
652             );
653             my $experimental_regexp = join('|', keys %experimental);
654             sub _experimental_bundle {
655 46     46   424 my ($version, $obj);
656              
657             shift->Document->find( sub {
658 507 100 100 507   6613 return '' unless $_[1]->isa('PPI::Statement::Include')
659             and $_[1]->pragma eq 'experimental';
660              
661 2         74 my @child = $_[1]->schildren;
662 2         33 my @args = @child[1..$#child]; # skip 'use', 'experimental' and ';'
663 2         5 foreach my $arg (@args) {
664 5         9 my $v = 0;
665 5 50       13 $v = $1 if ($arg->content =~ /:(5\.\d+)(?:\.\d+)?/);
666 5 100       44 $v = max($v, $experimental{$1}) if ($arg->content =~ /\b($experimental_regexp)\b/);
667              
668 5 100 50     184 if ($v and $v > ($version || 0) ) {
      66        
669 1         2 $version = $v;
670 1         3 $obj = $_[1];
671             }
672             }
673 2         6 return '';
674 46         113 } );
675              
676 46 100       744 return (defined($version)?"$version.0":undef, $obj);
677             }
678              
679             my %SCHEDULED_BLOCK =
680             (
681             'INIT' => '5.006',
682             'CHECK' => '5.006002',
683             'UNITCHECK' => '5.010',
684             );
685              
686             sub _scheduled_blocks
687             {
688 46     46   81 my @versions;
689 46         78 my ($version, $obj);
690              
691             shift->Document->find( sub {
692 507 100   507   5933 $_[1]->isa('PPI::Statement::Scheduled') or return '';
693 4 50       17 ($_[1]->children)[0]->isa('PPI::Token::Word') or return '';
694 4         34 my $function = (($_[1]->children)[0])->content;
695 4 100       32 exists( $SCHEDULED_BLOCK{ $function }) or return '';
696              
697 3         8 my $v = $SCHEDULED_BLOCK{ ($_[1]->children)[0]->content };
698 3 50 50     43 if ($v and $v > ($version || 0) ) {
      33        
699 3         6 $version = $v;
700 3         4 $obj = $_[1];
701             }
702              
703 3         40 return '';
704 46         99 } );
705 46 100       705 return (defined($version) ? $version : undef, $obj);
706             }
707              
708             sub _regex {
709 52     52   116 my @versions;
710 52         100 my ($version, $obj);
711             shift->Document->find( sub {
712             return '' unless
713 510 100   510   6219 grep { $_[1]->isa($_) }
  1530         4793  
714             qw/PPI::Token::QuoteLike::Regexp PPI::Token::Regexp::Match PPI::Token::Regexp::Substitute/;
715 14         99 my $re = PPIx::Regexp->new( $_[1] );
716 14         57422 my $v = $re->perl_version_introduced;
717 14 50 50     4314 if ($v and $v > ($version || 0) ) {
      33        
718 14         38 $version = $v;
719 14         32 $obj = $_[1];
720             }
721 14         159 return '';
722 52         158 } );
723 52 100 100     1862 $version = undef if ($version and $version eq '5.000');
724 52         173 return ($version, $obj);
725             }
726              
727             sub _each_argument {
728 88     88   331 my ($version, $obj);
729             shift->Document->find( sub {
730 815 100   815   11620 $_[1]->isa('PPI::Token::Word') or return '';
731 117 100       328 $_[1]->content =~ '^(each|keys|values)$' or return '';
732 44 100       554 return '' if is_method_call($_[1]);
733 42         1617 my $next = $_[1]->snext_sibling;
734 42 100       1024 $next = $next->schild(0)->schild(0) if $next->isa('PPI::Structure::List');
735 41 100       724 if($next->isa('PPI::Token::Cast')) {
    100          
    100          
    100          
736 4 100 50     13 if($next->content eq '@' && 5.012 > ($version || 0)) {
    50 66        
      0        
      33        
737 3         34 $version = 5.012;
738 3         16 $obj = $_[1]->parent;
739             } elsif($next->content eq '$' && 5.014 > ($version || 0)) {
740 0         0 $version = 5.014;
741 0         0 $obj = $_[1]->parent;
742             }
743             } elsif($next->isa('PPI::Token::Symbol')) {
744 28 100 100     133 if($next->raw_type eq '@' && 5.012 > ($version || 0)) {
    100 100        
      100        
      66        
745 7         86 $version = 5.012;
746 7         30 $obj = $_[1]->parent;
747             } elsif($next->raw_type eq '$' && 5.014 > ($version || 0)) {
748 14         272 $version = 5.014;
749 14         50 $obj = $_[1]->parent;
750             }
751             } elsif($next->isa('PPI::Token::Operator')) { # % $a
752 1         4 return '';
753             } elsif($_[1]->parent->isa('PPI::Statement::Sub')) { # sub each|keys|values
754 2         15 return '';
755             } else { # function call or other should be reference
756 6 50 50     76 if(5.014 > ($version || 0)) {
757 6         20 $version = 5.014;
758 6         15 $obj = $_[1]->parent;
759             }
760             }
761 38 100 100     409 return 1 if ($version and $version == 5.014);
762 17         50 return '';
763 88         251 } );
764 88 100       2178 return (defined($version)?"$version":undef, $obj);
765             }
766              
767             #Is string (first argument) in list (other arguments)
768             sub _str_in_list {
769 7     7   15 my $str = shift;
770 7         17 foreach my $s (@_) {
771 11 100       32 return 1 if $s eq $str;
772             }
773 4         27 return 0;
774             }
775              
776              
777             sub _binmode_2_arg {
778 55     55   131 my ($version, $obj);
779             shift->Document->find_first( sub {
780 579     579   6343 my $main_element=$_[1];
781 579 100       1821 $main_element->isa('PPI::Token::Word') or return '';
782 71 100       179 $main_element->content eq 'binmode' or return '';
783 10 50       65 return '' if is_hash_key($main_element);
784 10 50       444 return '' if is_method_call($main_element);
785 10 50       301 return '' if is_subroutine_name($main_element);
786 10 50       236 return '' if is_included_module_name($main_element);
787 10 50       274 return '' if is_package_declaration($main_element);
788 10         225 my @arguments = parse_arg_list($main_element);
789 10 100       1220 if ( scalar @arguments == 2 ) {
790 8         16 my $arg2=$arguments[1][0];
791 8 100       29 if ( $arg2->isa('PPI::Token::Quote')) { #check second argument
792 7         31 my $str = $arg2->string;
793 7         81 $str =~ s/^\s+//s;
794 7         25 $str =~ s/\s+$//s;
795 7         22 $str =~ s/:\s+/:/g;
796 7 100 100     18 if ( !_str_in_list( $str => qw/:raw :crlf/) and $str !~ /[\$\@\%]/) {
797 3         7 $version = 5.008;
798 3         6 $obj = $main_element;
799 3         13 return 1;
800             }
801             }
802 5 50       14 if (!$version) {
803 5         8 $version = 5.006;
804 5         8 $obj = $main_element;
805             }
806             }
807 7         22 return '';
808 55         136 } );
809 55         952 return ($version, $obj);
810             }
811              
812              
813              
814             #http://perldoc.perl.org/functions/readdir.html
815             #while(readdir $dh) requires perl 5.12
816             sub _while_readdir {
817             shift->Document->find_first( sub {
818 579 100   579   7076 $_[1]->isa('PPI::Token::Word') or return '';
819 71 100       162 $_[1]->content eq 'while' or return '';
820 8 50       52 return '' if is_hash_key($_[1]);
821 8 50       520 return '' if is_method_call($_[1]);
822 8 100       209 my $e1 = $_[1]->next_sibling or return '';
823 7 50       132 if ($e1->isa('PPI::Structure::Condition')) { #while ()
824 7         36 my @children = $e1->children;
825 7         39 $e1 = $children[0];
826             }
827 7 50       21 $e1->isa('PPI::Statement::Expression') or return '';
828 7         22 my @children = $e1->schildren;
829 7         112 $e1 = $children[0];
830              
831 7 100       23 $e1->isa('PPI::Token::Word') or return '';
832 6 100       13 $e1->content eq 'readdir' or return '';
833 5 50       21 return 1 if @children == 1; #incorrect call
834 5 100       13 return '' if @children > 2; #not only readdir
835 3         6 $e1 = $children[1];
836 3 50 66     15 $e1->isa('PPI::Structure::List') or $e1->isa('PPI::Token::Symbol') or return '';
837             #readdir($dh) or readdir $dh
838              
839 3         11 return 1;
840 50     50   157 } );
841             }
842              
843             sub _perl_5012_pragmas {
844             shift->Document->find_first( sub {
845             $_[1]->isa('PPI::Statement::Include')
846             and
847 404 100   404   5266 $MATCHES{_perl_5012_pragmas}->{$_[1]->pragma}
848 41     41   106 } );
849             }
850              
851             sub _sort_subref {
852             shift->Document->find_first( sub {
853 338 100   338   4155 $_[1]->isa('PPI::Token::Word') or return '';
854 42 100       117 $_[1]->content eq 'sort' or return '';
855 10 50       93 is_function_call($_[1]) or return '';
856 10         3191 my $e1 = $_[1]->next_sibling;
857 10 100       299 $e1->isa('PPI::Token::Whitespace') or return '';
858 9         32 $e1 = $e1->next_sibling;
859 9 100 100     169 _get_resulting_sigil($e1) || '' eq '$' or return '';
860 7         550 $e1 = $e1->next_sibling;
861 7 100       141 $e1->isa('PPI::Token::Whitespace') or return '';
862 6         17 $e1 = $e1->next_sibling;
863 6 100 100     145 $e1->isa('PPI::Token::Word') or $e1->isa('PPI::Token::Symbol')
      100        
      100        
864             or $e1->isa('PPI::Token::Cast') or $e1->isa('PPI::Structure::List') or return '';
865 5         41 return 1;
866 33     33   158 } );
867             }
868              
869             sub _open_temp {
870             shift->Document->find_first( sub {
871 391 100   391   4850 $_[1]->isa('PPI::Statement') or return '';
872 60         157 my @children = $_[1]->children;
873             #@children >= 7 or return '';
874 60         300 my $main_element = $children[0];
875 60 100       212 $main_element->isa('PPI::Token::Word') or return '';
876 34 100       77 $main_element->content eq 'open' or return '';
877 7         41 my @arguments = parse_arg_list($main_element);
878 7 100 66     1326 if ( scalar @arguments == 3 and scalar(@{$arguments[2]}) == 1) {
  5         18  
879 5         9 my $arg3 = $arguments[2][0];
880 5 100 66     23 if ($arg3->isa('PPI::Token::Word') and $arg3->content eq 'undef') {
881 3         17 return 1;
882             }
883             }
884 4         16 return '';
885 33     33   106 } );
886             }
887              
888             sub _open_scalar {
889             shift->Document->find_first( sub {
890 395 100   395   4807 $_[1]->isa('PPI::Statement') or return '';
891 61         178 my @children = $_[1]->children;
892             #@children >= 7 or return '';
893 61         315 my $main_element = $children[0];
894 61 100       222 $main_element->isa('PPI::Token::Word') or return '';
895 35 100       100 $main_element->content eq 'open' or return '';
896 8         51 my @arguments = parse_arg_list($main_element);
897 8 100       1717 if ( scalar @arguments == 3) {
898 6         14 my $arg3 = $arguments[2][0];
899 6 100 66     38 if ($arg3->isa('PPI::Token::Cast') and $arg3->content eq '\\') {
900 4         24 return 1;
901             }
902             }
903 4         17 return '';
904 34     34   116 } );
905             }
906              
907             # exists(&subr) new in 5.6.0 #
908             sub _exists_subr {
909 32     32   174 my ($pmv) = @_;
910             $pmv->Document->find_first(sub {
911 360     360   3938 my ($document, $elem) = @_;
912 360 100 100     1258 if ($elem->isa('PPI::Token::Word')
      100        
      66        
      100        
      100        
913             && $elem eq 'exists'
914             && is_function_call($elem)
915             && ($elem = first_arg($elem))
916             && (_get_resulting_sigil($elem) || '') eq '&') {
917 5         98 return 1;
918             } else {
919 355         1841 return 0;
920             }
921 32         91 });
922             }
923              
924             sub _get_resulting_sigil {
925 19     19   3935 my $elem = shift;
926 19 100       147 if ($elem->isa('PPI::Token::Cast')) {
    100          
927 3         11 return $elem->content;
928             } elsif ($elem->isa('PPI::Token::Symbol')) {
929 13         66 return $elem->symbol_type;
930             } else {
931 3         23 return undef;
932             }
933             }
934              
935              
936             sub _postfix_when {
937             shift->Document->find_first( sub {
938 524     524   5520 my $main_element=$_[1];
939 524 100       1670 $main_element->isa('PPI::Token::Word') or return '';
940 61 100       169 $main_element->content eq 'when' or return '';
941 5 50       53 return '' if is_hash_key($main_element);
942 5 50       534 return '' if is_method_call($main_element);
943 5 50       260 return '' if is_subroutine_name($main_element);
944 5 50       306 return '' if is_included_module_name($main_element);
945 5 50       160 return '' if is_package_declaration($main_element);
946 5         130 my $stmnt = $main_element->statement();
947 5 50       66 return '' if !$stmnt;
948 5 100       31 return '' if $stmnt->isa('PPI::Statement::When');
949 3         10 return 1;
950 46     46   145 } );
951             }
952              
953             sub _yada_yada_yada {
954             shift->Document->find_first( sub {
955 551 100 100 551   6851 $_[1]->isa('PPI::Token::Operator')
956             and $_[1]->content eq '...' or return '';
957 8         68 my @child = $_[1]->parent->schildren;
958 8 100       123 @child == 1 and return 1;
959 3 100       11 if (@child == 2) {
960 1         7 $child[1]->isa('PPI::Token::Structure')
961             }
962 51     51   146 } );
963             }
964              
965             sub _state_declaration {
966             shift->Document->find_first( sub {
967 421 100 66 421   5149 $_[1]->isa('PPI::Statement::Variable')
968             and ($_[1]->children)[0]->isa('PPI::Token::Word')
969             and ($_[1]->children)[0]->content eq 'state'
970 38     38   96 } );
971             }
972              
973             sub _stacked_labels {
974             shift->Document->find_first( sub {
975 0 0   0   0 $_[1]->isa('PPI::Statement::Compound') || return '';
976 0 0       0 $_[1]->schild(0)->isa('PPI::Token::Label') || return '';
977              
978 0   0     0 my $next = $_[1]->snext_sibling || return '';
979              
980 0 0 0     0 if ( $next->isa('PPI::Statement::Compound')
981             && $next->schild(0)->isa('PPI::Token::Label')) {
982 0         0 return 1;
983             }
984              
985 0         0 0;
986 0     0   0 } );
987             }
988              
989             sub _internals_svreadonly {
990             shift->Document->find_first( sub {
991 324 100 100 324   4571 $_[1]->isa('PPI::Statement')
992             and ($_[1]->children)[0]->isa('PPI::Token::Word')
993             and ($_[1]->children)[0]->content eq 'Internals::SvREADONLY'
994 30     30   90 } );
995             }
996              
997             sub _pkg_name_version {
998             shift->Document->find_first( sub {
999 502 100   502   5985 $_[1]->isa('PPI::Statement::Package') or return '';
1000 9         27 my @child = $_[1]->schildren();
1001 9 50       138 $child[0]->isa('PPI::Token::Word') or return '';
1002 9 50       24 $child[0]->content eq 'package' or return '';
1003 9 50       51 $child[1]->isa('PPI::Token::Word') or return '';
1004 9 100       37 $child[2]->isa('PPI::Token::Number') or return '';
1005 6         14 return 1;
1006 51     51   147 } );
1007             }
1008              
1009             sub _perl_5010_pragmas {
1010             shift->Document->find_first( sub {
1011             $_[1]->isa('PPI::Statement::Include')
1012             and
1013 312 100   312   4048 $MATCHES{_perl_5010_pragmas}->{$_[1]->pragma}
1014 34     34   655 } );
1015             }
1016              
1017             sub _perl_5010_operators {
1018             shift->Document->find_first( sub {
1019             $_[1]->isa('PPI::Token::Operator')
1020             and
1021 426 100   426   5126 $MATCHES{_perl_5010_operators}->{$_[1]->content}
1022 36     36   125 } );
1023             }
1024              
1025             sub _perl_5010_magic {
1026             shift->Document->find_first( sub {
1027             $_[1]->isa('PPI::Token::Magic')
1028             and
1029 401 100   401   5006 $MATCHES{_perl_5010_magic}->{$_[1]->symbol}
1030 35     35   82 } );
1031             }
1032              
1033             sub _perl_5008_pragmas {
1034             shift->Document->find_first( sub {
1035             $_[1]->isa('PPI::Statement::Include')
1036             and
1037 295 100   295   3698 $MATCHES{_perl_5008_pragmas}->{$_[1]->pragma}
1038 27     27   71 } );
1039             }
1040              
1041             # 5.8.3: Reading $^E now preserves $!. Previously, the C code implementing $^E did not preserve errno, so reading $^E could cause errno and therefore $! to change unexpectedly.
1042             sub _bugfix_magic_errno {
1043 33     33   671 my $Document = shift->Document;
1044             my $element = $Document->find_first( sub {
1045 393     393   4844 $_[1]->isa('PPI::Token::Magic')
1046             and
1047             $_[1]->symbol eq '$^E'
1048 33   100     151 } ) || return undef;
1049             #$^E is more rare than $!, so search for it first and return it
1050             $Document->find_any( sub {
1051 4 100   4   83 $_[1]->isa('PPI::Token::Magic')
1052             and
1053             $_[1]->symbol eq '$!'
1054 2 50       108 } ) || return '';
1055 2         105 return $element;
1056             }
1057              
1058             # utf8::is_utf requires 5.8.1 unlike the rest of utf8
1059             sub _is_utf8 {
1060             shift->Document->find_first( sub {
1061 381 100   381   5046 $_[1]->isa('PPI::Token::Word') or return '';
1062 42 50       138 $_[1] eq 'utf8::is_utf' or return '';
1063 0         0 return 1;
1064 31     31   81 } );
1065             }
1066              
1067             # version->new(5.005.004);
1068             sub _unquoted_versions {
1069             shift->Document->find_first( sub {
1070 381 100   381   4437 $_[1]->isa('PPI::Token::Number') or return '';
1071 21 50       63 $_[1]->{_subtype} or return '';
1072 0 0       0 $_[1]->{_subtype} eq 'base256' or return '';
1073 0 0       0 my $stmt = $_[1]->parent or return '';
1074 0 0       0 my $braces = $stmt->parent or return '';
1075 0 0       0 $braces->isa('PPI::Structure') or return '';
1076 0 0       0 $braces->braces eq '()' or return '';
1077 0 0       0 my $new = $braces->previous_sibling or return '';
1078 0 0       0 $new->isa('PPI::Token::Word') or return '';
1079 0 0       0 $new->content eq 'new' or return '';
1080 0 0       0 my $method = $new->previous_sibling or return '';
1081 0 0       0 $method->isa('PPI::Token::Operator') or return '';
1082 0 0       0 $method->content eq '->' or return '';
1083 0 0       0 my $_class = $method->previous_sibling or return '';
1084 0 0       0 $_class->isa('PPI::Token::Word') or return '';
1085 0 0       0 $_class->content eq 'version' or return '';
1086 0         0 1;
1087 31     31   77 } );
1088             }
1089              
1090             sub _pragma_utf8 {
1091             shift->Document->find_first( sub {
1092 332 100 100 332   4434 $_[1]->isa('PPI::Statement::Include')
      66        
      66        
1093             and
1094             (
1095             ($_[1]->module and $_[1]->module eq 'utf8')
1096             or
1097             ($_[1]->pragma and $_[1]->pragma eq 'utf8')
1098             )
1099             # This used to be just pragma(), but that was buggy in PPI v1.118
1100 28     28   67 } );
1101             }
1102              
1103             # Check for the use of 'use constant { ... }'
1104             sub _constant_hash {
1105             shift->Document->find_first( sub {
1106 342 100 66 342   4600 $_[1]->isa('PPI::Statement::Include')
      100        
      100        
1107             and
1108             $_[1]->type
1109             and
1110             $_[1]->type eq 'use'
1111             and
1112             $_[1]->module eq 'constant'
1113             and
1114             $_[1]->schild(2)->isa('PPI::Structure')
1115 29     29   67 } );
1116             }
1117              
1118             sub _perl_5006_pragmas {
1119             shift->Document->find_first( sub {
1120             $_[1]->isa('PPI::Statement::Include')
1121             and
1122 238 100   238   3087 $MATCHES{_perl_5006_pragmas}->{$_[1]->pragma}
1123 21     21   56 } );
1124             }
1125              
1126             sub _any_our_variables {
1127             shift->Document->find_first( sub {
1128 243 100   243   3193 $_[1]->isa('PPI::Statement::Variable')
1129             and
1130             $_[1]->type eq 'our'
1131 24     24   1270 } );
1132             }
1133              
1134             sub _any_binary_literals {
1135             shift->Document->find_first( sub {
1136 180     180   2115 $_[1]->isa('PPI::Token::Number::Binary')
1137 17     17   43 } );
1138             }
1139              
1140             sub _any_version_literals {
1141             shift->Document->find_first( sub {
1142 300     300   3308 $_[1]->isa('PPI::Token::Number::Version')
1143 25     25   662 } );
1144             }
1145              
1146              
1147             sub _magic_version {
1148             shift->Document->find_first( sub {
1149 274 100   274   3320 $_[1]->isa('PPI::Token::Magic')
1150             and
1151             $_[1]->symbol eq '$^V'
1152 21     21   66 } );
1153             }
1154              
1155             sub _any_attributes {
1156 22     22   668 shift->Document->find_first( 'Token::Attribute' );
1157             }
1158              
1159             sub _any_CHECK_blocks {
1160             shift->Document->find_first( sub {
1161 274 100   274   3210 $_[1]->isa('PPI::Statement::Scheduled')
1162             and
1163             $_[1]->type eq 'CHECK'
1164 21     21   84 } );
1165             }
1166              
1167             sub _any_qr_tokens {
1168 16     16   52 shift->Document->find_first( 'Token::QuoteLike::Regexp' );
1169             }
1170              
1171             sub _perl_5005_pragmas {
1172             shift->Document->find_first( sub {
1173             $_[1]->isa('PPI::Statement::Include')
1174             and
1175 149 100   149   1869 $MATCHES{_perl_5005_pragmas}->{$_[1]->pragma}
1176 15     15   44 } );
1177             }
1178              
1179             # A number of modules are highly indicative of using techniques
1180             # that are themselves version-dependent.
1181             sub _perl_5005_modules {
1182             shift->Document->find_first( sub {
1183 154 100 33 154   2402 $_[1]->isa('PPI::Statement::Include')
      33        
      33        
      33        
      33        
      33        
      100        
1184             and
1185             $_[1]->module
1186             and (
1187             $_[1]->module eq 'Tie::Array'
1188             or
1189             ($_[1]->module =~ /\bException\b/ and
1190             $_[1]->module !~ /^(?:CPAN)::/)
1191             or
1192             $_[1]->module =~ /\bThread\b/
1193             or
1194             $_[1]->module =~ /^Error\b/
1195             or
1196             $_[1]->module eq 'base'
1197             or
1198             $_[1]->module eq 'Errno'
1199             )
1200 13     13   43 } );
1201             }
1202              
1203             sub _any_tied_arrays {
1204             shift->Document->find_first( sub {
1205 154 100   154   1850 $_[1]->isa('PPI::Statement::Sub')
1206             and
1207             $_[1]->name eq 'TIEARRAY'
1208             } )
1209 13     13   38 }
1210              
1211             sub _any_quotelike_regexp {
1212 15     15   40 shift->Document->find_first( 'Token::QuoteLike::Regexp' );
1213             }
1214              
1215             sub _any_INIT_blocks {
1216             shift->Document->find_first( sub {
1217 173 100   173   2034 $_[1]->isa('PPI::Statement::Scheduled')
1218             and
1219             $_[1]->type eq 'INIT'
1220 15     15   43 } );
1221             }
1222              
1223             # You can't localize a soft reference
1224             sub _local_soft_reference {
1225             shift->Document->find_first( sub {
1226 316 100   316   3806 $_[1]->isa('PPI::Statement::Variable') or return '';
1227 8 100       34 $_[1]->type eq 'local' or return '';
1228              
1229             # The second child should be a '$' cast.
1230 2         99 my @child = $_[1]->schildren;
1231 2 50       40 scalar(@child) >= 2 or return '';
1232 2 50       8 $child[1]->isa('PPI::Token::Cast') or return '';
1233 2 50       6 $child[1]->content eq '$' or return '';
1234              
1235             # The third child should be a block
1236 2 50       15 $child[2]->isa('PPI::Structure::Block') or return '';
1237              
1238             # Inside the block should be a string in a statement
1239 2 50       11 my $statement = $child[2]->schild(0) or return '';
1240 2 50       44 $statement->isa('PPI::Statement') or return '';
1241 2 50       6 my $inside = $statement->schild(0) or return '';
1242 2 50       29 $inside->isa('PPI::Token::Quote') or return '';
1243              
1244             # This is indeed a localized soft reference
1245 2         5 return 1;
1246 28     28   652 } );
1247             }
1248              
1249             # Carp.pm did not have a $VERSION in 5.6.2
1250             # Therefore, even "use Carp 0" imposes a 5.8.0 dependency.
1251             sub _use_carp_version {
1252             shift->Document->find_first( sub {
1253 314 100   314   3703 $_[1]->isa('PPI::Statement::Include') or return '';
1254 7 50       23 $_[1]->module eq 'Carp' or return '';
1255              
1256 0         0 my $version = $_[1]->module_version;
1257 0   0     0 return !! ( defined $version and length "$version" );
1258 26     26   67 } );
1259             }
1260              
1261             sub _three_argument_open {
1262             shift->Document->find_first( sub {
1263 287 100   287   3532 $_[1]->isa('PPI::Statement') or return '';
1264 50         126 my @children = $_[1]->children;
1265             #@children >= 7 or return '';
1266 50         275 my $main_element = $children[0];
1267 50 100       188 $main_element->isa('PPI::Token::Word') or return '';
1268 30 100       73 $main_element->content eq 'open' or return '';
1269 13         84 my @arguments = parse_arg_list($main_element);
1270 13 100       2996 if ( scalar @arguments > 2 ) {
1271 7         25 return 1;
1272             }
1273 6         19 return '';
1274 31     31   125 } );
1275             }
1276              
1277             sub _substr_4_arg {
1278             shift->Document->find_first( sub {
1279 248     248   2765 my $main_element=$_[1];
1280 248 100       824 $main_element->isa('PPI::Token::Word') or return '';
1281 29 100       88 $main_element->content eq 'substr' or return '';
1282 7 50       71 return '' if is_hash_key($main_element);
1283 7 100       489 return '' if is_method_call($main_element);
1284 6 50       287 return '' if is_subroutine_name($main_element);
1285 6 50       267 return '' if is_included_module_name($main_element);
1286 6 50       202 return '' if is_package_declaration($main_element);
1287 6         177 my @arguments = parse_arg_list($main_element);
1288 6 100       1181 if ( scalar @arguments > 3 ) {
1289 3         12 return 1;
1290             }
1291 3         13 return '';
1292 22     22   123 } );
1293             }
1294              
1295             sub _mkdir_1_arg {
1296             shift->Document->find_first( sub {
1297 244     244   2708 my $main_element=$_[1];
1298 244 100       808 $main_element->isa('PPI::Token::Word') or return '';
1299 27 100       82 $main_element->content eq 'mkdir' or return '';
1300 6 50       39 return '' if is_hash_key($main_element);
1301 6 100       385 return '' if is_method_call($main_element);
1302 5 50       170 return '' if is_subroutine_name($main_element);
1303 5 50       153 return '' if is_included_module_name($main_element);
1304 5 50       133 return '' if is_package_declaration($main_element);
1305 5         115 my @arguments = parse_arg_list($main_element);
1306 5 100       607 if ( scalar @arguments != 2 ) {
1307 3         10 return 1;
1308             }
1309 2         8 return '';
1310 25     25   116 } );
1311             }
1312              
1313             sub _splice_negative_length {
1314             shift->Document->find_first( sub {
1315 230     230   2449 my $main_element=$_[1];
1316 230 100       730 $main_element->isa('PPI::Token::Word') or return '';
1317 27 100       71 $main_element->content eq 'splice' or return '';
1318 9 50       54 return '' if is_hash_key($main_element);
1319 9 100       586 return '' if is_method_call($main_element);
1320 8 50       239 return '' if is_subroutine_name($main_element);
1321 8 50       209 return '' if is_included_module_name($main_element);
1322 8 50       208 return '' if is_package_declaration($main_element);
1323              
1324 8         180 my @arguments = parse_arg_list($main_element);
1325 8 100       1636 if ( scalar @arguments < 3 ) {
1326 3         11 return '';
1327             }
1328 5         9 my $arg=$arguments[2];
1329 5 50       16 if (ref($arg) eq 'ARRAY') {
1330 5         9 $arg=$arg->[0];
1331             }
1332 5 50       15 if ($arg->isa('PPI::Token::Number')) {
1333 5 100       16 if ($arg->literal<0) {
1334 3         50 return 1;
1335             } else {
1336 2         36 return '';
1337             }
1338             }
1339 0         0 return '';
1340 22     22   80 } );
1341              
1342             }
1343              
1344             sub _postfix_foreach {
1345             shift->Document->find_first( sub {
1346 197     197   2237 my $main_element=$_[1];
1347 197 100       661 $main_element->isa('PPI::Token::Word') or return '';
1348 26 100       71 $main_element->content eq 'foreach' or return '';
1349 4 50       36 return '' if is_hash_key($main_element);
1350 4 50       369 return '' if is_method_call($main_element);
1351 4 50       187 return '' if is_subroutine_name($main_element);
1352 4 50       212 return '' if is_included_module_name($main_element);
1353 4 50       125 return '' if is_package_declaration($main_element);
1354 4         98 my $stmnt = $main_element->statement();
1355 4 50       55 return '' if !$stmnt;
1356 4 100       19 return '' if $stmnt->isa('PPI::Statement::Compound');
1357 3         10 return 1;
1358 18     18   86 } );
1359             }
1360              
1361             # weak references require perl 5.6
1362             # will not work in case of importing several
1363             sub _weaken {
1364             shift->Document->find_first( sub {
1365             (
1366 325 100 100 325   5399 $_[1]->isa('PPI::Statement::Include')
      66        
      100        
      100        
1367             and
1368             $_[1]->module eq 'Scalar::Util'
1369             and
1370             $_[1]->content =~ /[^:]\b(?:weaken|isweak)\b[^:]/
1371             )
1372             or
1373             (
1374             $_[1]->isa('PPI::Token::Word')
1375             and
1376             (
1377             $_[1]->content eq 'Scalar::Util::isweak'
1378             or
1379             $_[1]->content eq 'Scalar::Util::weaken'
1380             )
1381             #and
1382             #is_function_call($_[1])
1383             )
1384 32     32   113 } );
1385             }
1386              
1387             sub _5005_variables {
1388             shift->Document->find_first( sub {
1389 167 100 66 167   2034 $_[1]->isa('PPI::Token::Magic')
1390             and
1391             ($_[1]->symbol eq '$!' or $_[1]->symbol eq '$^R')
1392 16     16   615 } );
1393             }
1394              
1395             #added in 5.5
1396             sub _bareword_double_colon {
1397             shift->Document->find_first( sub {
1398 189 100   189   2571 $_[1]->isa('PPI::Token::Word')
1399             and
1400             $_[1]->content =~ /::$/
1401 21     21   81 } );
1402             }
1403              
1404              
1405              
1406             #####################################################################
1407             # Support Functions
1408              
1409             # Let sub be a function, object method, and static method
1410             sub _SELF {
1411 228     228   349 my $param = shift;
1412 228 100       1264 if ( _INSTANCE($param->[0], 'Perl::MinimumVersion') ) {
1413 226         694 return shift @$param;
1414             }
1415 2 50 33     14 if (
1416             _CLASS($param->[0])
1417             and
1418             $param->[0]->isa('Perl::MinimumVersion')
1419             ) {
1420 2         40 my $class = shift @$param;
1421 2         6 my $options = shift @$param;
1422 2         8 return $class->new($options);
1423             }
1424 0         0 Perl::MinimumVersion->new(shift @$param);
1425             }
1426              
1427             # Find the maximum version, ignoring problems
1428             sub _max {
1429 18 100 100 18   1115 defined $_[0] and "$_[0]" eq PMV and shift;
1430              
1431             # Filter and prepare for a Schwartian maximum
1432             my @valid = map {
1433 26 50       117 [ $_, $_->isa('Perl::MinimumVersion::Reason') ? $_->version : $_ ]
1434             } grep {
1435 18 50       54 _INSTANCE($_, 'Perl::MinimumVersion::Reason')
  36 100       584  
1436             or
1437             _INSTANCE($_, 'version')
1438             } @_ or return '';
1439              
1440             # Find the maximum
1441 12         23 my $max = shift @valid;
1442 12         27 foreach my $it ( @valid ) {
1443 14 100       62 $max = $it if $it->[1] > $max->[1];
1444             }
1445              
1446 12         119 return $max->[0];
1447             }
1448              
1449             1;
1450              
1451             =pod
1452              
1453             =head1 BUGS
1454              
1455             B does a reasonable job of catching the best-known
1456             explicit version dependencies.
1457              
1458             B it is exceedingly easy to add a new syntax check, so if you
1459             find something this is missing, copy and paste one of the existing
1460             5 line checking functions, modify it to find what you want, and report it
1461             to rt.cpan.org, along with the version needed.
1462              
1463             I don't even need an entire diff... just the function and version.
1464              
1465             =head1 TO DO
1466              
1467             B
1468              
1469             - Perl 5.10 operators and language structures
1470              
1471             - Three-argument open
1472              
1473             B
1474              
1475             B
1476              
1477             _while_readdir for postfix while without brackets
1478              
1479             B
1480             C, C<...>, and C)>
1481              
1482             =head1 SUPPORT
1483              
1484             All bugs should be filed via the CPAN bug tracker at
1485              
1486             L
1487              
1488             For other issues, or commercial enhancement or support, contact the author.
1489              
1490             =head1 AUTHORS
1491              
1492             Adam Kennedy Eadamk@cpan.orgE
1493              
1494             =head1 SEE ALSO
1495              
1496             L - the command-line script for running C
1497             on your code.
1498              
1499             L - another module which does the same thing.
1500             It's a lot faster, but only supports Perl 5.8.1+.
1501              
1502             L, L, L
1503              
1504             =head1 REPOSITORY
1505              
1506             L
1507              
1508             =head1 COPYRIGHT
1509              
1510             Copyright 2005 - 2014 Adam Kennedy.
1511              
1512             This program is free software; you can redistribute
1513             it and/or modify it under the same terms as Perl itself.
1514              
1515             The full text of the license can be found in the
1516             LICENSE file included with this module.
1517              
1518             =cut