File Coverage

blib/lib/Perl/Version/Bumper.pm
Criterion Covered Total %
statement 287 307 93.4
branch 135 180 75.0
condition 120 154 77.9
subroutine 42 43 97.6
pod 16 16 100.0
total 600 700 85.7


line stmt bran cond sub pod time code
1 6     6   1240730 use v5.10;
  6         23  
2              
3             package Perl::Version::Bumper;
4             $Perl::Version::Bumper::VERSION = '0.245';
5              
6 6     6   57 use strict;
  6         12  
  6         191  
7 6     6   27 use warnings;
  6         10  
  6         345  
8 6     6   2267 use version;
  6         9936  
  6         37  
9              
10 6     6   4028 use Path::Tiny ();
  6         58101  
  6         198  
11 6     6   4283 use PPI::Document;
  6         1421580  
  6         341  
12 6     6   67 use PPI::Token::Operator;
  6         20  
  6         219  
13 6     6   46 use PPI::Token::Attribute;
  6         22  
  6         204  
14 6     6   33 use Carp qw( carp croak );
  6         12  
  6         3075  
15              
16             # CLASS METHODS
17              
18             my $feature_version;
19              
20 43     43 1 481778 sub feature_version { $feature_version }
21              
22             # reconstruct everything we know about every feature
23             # from the $DATA variable defined at the end of the file
24             my $FEATURE_DATA;
25              
26             sub feature_data {
27 6     6 1 12 my %feature;
28 6         220 for ( grep !/\A(?:=|\z)/, split /\n/, $FEATURE_DATA ) {
29 180 100       678 if (/\A *([1-9][0-9.]*)/) { # header line
30 6         25 $feature_version = version_fmt($1);
31 6         25 next;
32             }
33 174         320 my $feature = substr $_, 0, 33, ''; # %32s
34 174         288 my $known = substr $_, 0, 9, ''; # %-8s
35 174         273 my $enabled = substr $_, 0, 9, ''; # %-8s
36 174         263 my $disabled = substr $_, 0, 9, ''; # %-8s
37 174         272 my $removed = substr $_, 0, 9, ''; # %-8s
38 174         362 my @compat = split ' '; # %s
39 174         573 y/ //d for $feature, $known, $enabled, $disabled;
40 174         596 $feature{$feature}{known} = $known;
41 174 100       397 $feature{$feature}{enabled} = $enabled if $enabled;
42 174 100       329 $feature{$feature}{disabled} = $disabled if $disabled;
43 174 100       357 $feature{$feature}{removed} = $removed if $removed;
44 174 100       435 $feature{$feature}{compat} = {@compat} if @compat;
45 174 100       485 $feature{$feature}{unfeature} = 1 if $disabled;
46             }
47 6         140 return \%feature;
48             }
49              
50             my %feature = %{ feature_data() };
51              
52             # EXPORTABLE FUNCTIONS
53              
54 6     6   53 use Exporter 'import';
  6         11  
  6         40112  
55              
56             our @EXPORT_OK = qw(
57             version_fmt
58             version_use
59             stable_version
60             stable_version_inc
61             stable_version_dec
62             );
63              
64             # return a normalized version of a plausible Perl version number (or die)
65             sub version_fmt {
66 12860   66 12860 1 899852 my $o = shift // $];
67 12860 50       42405 $o = $] unless length $o;
68 12860         191382 my $v = version::->parse($o)->numify; # accept everything
69 12859 100       211702 return $v < 5.010
70             ? croak "Unsupported Perl version: $o"
71             : sprintf "%.3f", $v; # Perl version bundle
72             }
73              
74             # return a normalized version, suitable for "use VERSION"
75             sub version_use {
76 3865   33 3865 1 11961 my $o = shift // $];
77 3865 50       12373 $o = $] unless length $o;
78 3865         30202 my $v = version::->parse($o)->numify; # accept everything
79 3865 50       56053 return $v < 5.010
80             ? croak "Unsupported Perl version: $o"
81             : sprintf 'v5.%d', substr( $v, 2, 3 ); # Perl version bundle
82             }
83              
84             # return the closest stable version number lower than the parameter
85             sub stable_version {
86 7834     7834 1 2955293 my $v = version_fmt(shift);
87 7834         35065 $v *= 1000;
88 7834         63798 return sprintf "%.3f", ( int($v) - $v % 2 ) / 1000;
89             }
90              
91             # increment the version number to the next stable version
92             sub stable_version_inc {
93 3422     3422 1 7567967 my $v = stable_version(shift); # closest previous stable
94 3422         173823 return sprintf "%.3f", $v + 0.002;
95             }
96              
97             # decrement the version number to the previous stable version
98             sub stable_version_dec {
99 490     490 1 7373 my $v = version_fmt(shift); # format the version
100 490         7243 my $s = stable_version($v); # get the closest previous stable
101 490 100       53902 return $v ne $s
102             ? $s # dev -> previous stable
103             : sprintf "%.3f", $s - 0.002 # previous stable
104             }
105              
106             # CONSTRUCTOR
107              
108             sub _feature_in_bundle {
109 3861     3861   11398 my $version_num = shift;
110             return {
111             known => {
112             map +( $_ => $feature{$_}{known} ),
113             grep exists $feature{$_}{known} && $version_num >= $feature{$_}{known},
114             keys %feature
115             },
116             enabled => {
117             map +( $_ => $feature{$_}{enabled} ),
118             grep !exists $feature{$_}{disabled} || $version_num < $feature{$_}{disabled},
119             grep exists $feature{$_}{enabled} && $version_num >= $feature{$_}{enabled},
120             keys %feature
121             },
122             disabled => {
123             map +( $_ => $feature{$_}{disabled} ),
124             grep exists $feature{$_}{disabled} && $version_num >= $feature{$_}{disabled},
125 3861   66     989836 keys %feature
      100        
      100        
      100        
126             },
127             };
128             }
129              
130             sub new {
131              
132             # stolen from Moo::Object
133 3869     3869 1 122178 my $class = shift;
134             my $args = scalar @_ == 1
135             ? ref $_[0] eq 'HASH'
136 3869 0       29847 ? { %{ $_[0] } }
  0 50       0  
    50          
137             : Carp::croak("Single parameters to new() must be a HASH ref"
138             . " data => ". $_[0])
139             : @_ % 2
140             ? Carp::croak("The new() method for $class expects a hash reference or a"
141             . " key/value list. You passed an odd number of arguments")
142             : {@_}
143             ;
144              
145             # handle the version attribute
146 3869   66     18078 my $version_arg = $args->{version} // stable_version($]);
147 3869         12759 my $version_num = version_fmt( $version_arg );
148 3866 100       18658 croak "Unsupported Perl version: $version_arg (greater than $feature_version)"
149             if $version_num > $feature_version;
150 3863 100       13261 croak "$args->{version} is not a stable Perl version"
151             if $version_num ne stable_version($version_num);
152              
153 3861         14056 return bless {
154             version => version_use($version_num),
155             version_num => $version_num,
156             feature_in_bundle => _feature_in_bundle($version_num),
157             }, $class;
158             };
159              
160             # ATTRIBUTES
161              
162 12584     12584 1 177612 sub version { shift->{version} }
163              
164 15199     15199 1 103208 sub version_num { shift->{version_num} }
165              
166             # PRIVATE FUNCTIONS
167              
168             sub __evaluate {
169             map ref()
170             ? $_->[0] eq 'CODE'
171       0     ? sub { } # leave anonymous subs as is
172 17559 0   17559   115282 : $_->[0] eq '[' ? [ __SUB__->( @$_[ 1 .. $#$_ ] ) ] # ARRAY
    0          
    0          
    50          
173             : $_->[0] eq '{' ? { __SUB__->( @$_[ 1 .. $#$_ ] ) } # HASH
174             : __SUB__->( @$_[ 1 .. $#$_ ] ) # LIST (flattened)
175             : $_, # SCALAR
176             @_;
177             }
178              
179             # given a list of PPI tokens, construct a Perl data structure
180             sub _ppi_list_to_perl_list {
181              
182             # are there constants we ought to know about?
183 17559 50   17559   795472 my $constants = ref $_[-1] eq 'HASH' ? pop @_ : {};
184              
185             # make sure we have tokens (i.e. deconstruct Statement and Structure objects)
186 17559         89819 my @tokens = grep $_->significant, map $_->tokens, @_;
187 17559         110292 my @stack = my $root = my $ptr = [];
188 17559         33200 my $prev;
189 17559         85784 while ( my $token = shift @tokens ) {
190 17580 0 66     108899 if ( $token->isa('PPI::Token::Structure') ) {
    50 33        
    100 33        
    50          
    50          
    50          
191 0 0       0 if ( $token =~ /\A[[{(]\z/ ) { # opening
    0          
192             $ptr = $token eq '{' && $prev && $prev eq 'sub' # sub { ... }
193 0 0 0     0 ? do { pop @{ $stack[-1] }; ['CODE'] } # drop 'sub' token
  0         0  
  0         0  
  0         0  
194             : ["$token"];
195 0         0 push @{ $stack[-1] }, $ptr;
  0         0  
196 0         0 push @stack, $ptr;
197             }
198             elsif ( $token =~ /\A[]})]\z/ ) { # closing
199 0         0 pop @stack;
200 0         0 $ptr = $stack[-1];
201             }
202             }
203             elsif ( $token eq ',' || $token eq '=>' ) { } # skip
204             elsif ( $token->isa('PPI::Token::Symbol') ) { # variable
205              
206             # construct the expression back (and keep the object around)
207 0         0 my $expr = PPI::Document->new( \join '', $token, @tokens );
208              
209             # PPI::Document -> PPI::Statement
210             # -> PPI::Token::Symbol (ignored), PPI::Sructure::Subscript (maybe)
211 0         0 my ( undef, $subscript ) = $expr->child(0)->children;
212 0 0 0     0 if ( $subscript && $subscript->isa('PPI::Structure::Subscript') ) {
213 0         0 shift @tokens for $subscript->tokens; # drop subcript tokens
214 0         0 push @$ptr, "$token$subscript"; # symbol + subscript
215             }
216             else {
217 0         0 push @$ptr, "$token"; # simple symbol
218             }
219             }
220             elsif ($token->isa('PPI::Token::Word') # undef
221             && $token eq 'undef'
222             && ( $tokens[0] ? $tokens[0] ne '=>' : !!1 ) )
223             {
224 0         0 push @$ptr, undef;
225             }
226             elsif ($token->isa('PPI::Token::HereDoc') ) { # heredoc
227 0         0 push @$ptr, join '', $token->heredoc;
228             }
229             else {
230 17493         730981 my $next_sibling = $token->snext_sibling;
231             push @$ptr,
232              
233             # maybe a known constant?
234             exists $constants->{$token} && ( $next_sibling ? $next_sibling ne '=>' : !!1 )
235             ? $constants->{$token}
236              
237             # various types of strings
238             : $token->can('literal') ? $token->literal
239 17493 0 33     749756 : $token->can('simplify') ? do {
    0          
    50          
    100          
    50          
240 225         4554 my $clone = $token->clone;
241 225 50 33     3595 $clone->simplify && $clone->can('literal')
242             ? $clone->literal
243             : "$clone";
244             }
245             : $token->can('string') ? $token->string
246              
247             # stop at the first operator
248             : $token->isa( 'PPI::Token::Operator' ) ? last
249              
250             # give up and just stringify
251             : "$token";
252             }
253 17580         544009 $prev = $token;
254             }
255 17559         49146 return __evaluate(@$root);
256             }
257              
258             sub _drop_statement {
259 12057     12057   40180 my ( $stmt, $keep_comments ) = @_;
260              
261             # remove non-significant elements before the statement
262 12057         44287 while ( my $prev_sibling = $stmt->previous_sibling ) {
263 12405 100       653346 last if $prev_sibling->significant;
264 12309 100       36295 last if $prev_sibling =~ /\n\z/;
265 348         3333 $prev_sibling->remove;
266             }
267              
268             # remove non-significant elements after the statement
269             # if there was no significant element before it on the same line
270             # (i.e. it was the only statement on the line)
271 12057         141840 $stmt->document->index_locations;
272 12057 100 100     22922790 if ( !$stmt->sprevious_sibling
273             || $stmt->sprevious_sibling->location->[0] ne $stmt->location->[0] )
274             {
275             # collect non-significant elements until next newline (included)
276 11961         1229061 my ( $next, @to_drop ) = ( $stmt );
277 11961         40236 while ( $next = $next->next_sibling ) {
278 12276 100       331502 last if $next->significant;
279 12189         23938 push @to_drop, $next;
280 12189 100       44627 last if $next eq "\n";
281             }
282              
283             # do not drop comments if asked to keep them
284 11961 100 100     269012 @to_drop = grep !$_->isa('PPI::Token::Comment') && $_ ne "\n", @to_drop
      100        
285             if $keep_comments && grep $_->isa('PPI::Token::Comment'), @to_drop;
286 11961         55063 $_->remove for @to_drop;
287              
288 11961         516668 $stmt->document->flush_locations;
289             }
290              
291             # and finally remove it
292 12057         4216422 $stmt->remove;
293             }
294              
295             sub _drop_bare {
296 11055     11055   51398 my ( $type, $module, $doc ) = @_;
297             my $use_module = $doc->find(
298             sub {
299 76668     76668   831769 my ( $root, $elem ) = @_;
300 76668 100 100     305073 return !!1
      100        
      66        
301             if $elem->isa('PPI::Statement::Include')
302             && $elem->module eq $module
303             && $elem->type eq $type
304             && !$elem->arguments; # bare use module
305 75474         887440 return; # only top-level
306             }
307 11055         92675 );
308 11055 100       172376 if ( ref $use_module ) {
309 1194         5480 _drop_statement($_) for @$use_module;
310             }
311 11055         77246 return;
312             }
313              
314             sub _find_include {
315 146544     146544   412088 my ( $module, $doc, $type ) = @_;
316             my $found = $doc->find(
317             sub {
318 3444393     3444393   36235969 my ( $root, $elem ) = @_;
319 3444393 100 100     11394183 return !!1
320             if $elem->isa('PPI::Statement::Include')
321             && $elem->module eq $module;
322 3415770         16506849 return !!0;
323             }
324 146544         952386 );
325 146544 50       2407274 croak "Bad condition for PPI::Node->find"
326             unless defined $found; # error
327 146544 100       637462 return unless $found; # nothing found
328 12897 100       100242 return $type ? grep $_->type eq $type, @$found : @$found;
329             }
330              
331             sub _version_stmts {
332 15162     15162   42269 my ($doc) = @_;
333             my $version_stmts = $doc->find(
334             sub {
335 653718     653718   6916571 my ( $root, $elem ) = @_;
336 653718 100 100     2318970 return !!1 if $elem->isa('PPI::Statement::Include') && $elem->version;
337 646365         3024382 return !!0;
338             }
339 15162         201291 );
340 15162 50       310447 croak "Bad condition for PPI::Node->find"
341             unless defined $version_stmts;
342 15162 100       79266 return $version_stmts ? @$version_stmts : ();
343             }
344              
345             my %feature_shine = (
346             when_enabled => {
347              
348             # the 'bitwise' feature may break bitwise operators,
349             # so disable it when bitwise operators are detected
350             bitwise => sub {
351             my ($doc) = @_;
352              
353             # this only matters for code using bitwise ops
354             return unless $doc->find(
355             sub {
356             my ( $root, $elem ) = @_;
357             $elem->isa('PPI::Token::Operator')
358             && $elem =~ /\A[&|~^]=?\z/;
359             }
360             );
361              
362             # the `use VERSION` inserted earlier is always the first in the doc
363             my $insert_point = ( _version_stmts($doc) )[0];
364             my $indent = $insert_point->previous_sibling
365             && $insert_point->previous_sibling->isa('PPI::Token::Whitespace')
366             ? $insert_point->previous_sibling
367             : '';
368             my $no_feature_bitwise =
369             PPI::Document->new( \"no feature 'bitwise';\n" );
370             $insert_point->insert_after( $_->remove )
371             for $no_feature_bitwise->elements;
372              
373             # also add an IMPORTANT comment to warn users
374             $insert_point = $insert_point->snext_sibling;
375             my $todo_comment = PPI::Document->new( \( << "TODO_COMMENT" ) );
376              
377             $indent# IMPORTANT: Please double-check the use of bitwise operators
378             $indent# before removing the `no feature 'bitwise';` line below.
379             $indent# See manual pages 'feature' (section "The 'bitwise' feature")
380             $indent# and 'perlop' (section "Bitwise String Operators") for details.
381             TODO_COMMENT
382             $insert_point->insert_before( $_->remove )
383             for $todo_comment->elements;
384             $insert_point->insert_before( $indent->clone ) if $indent;
385             },
386              
387             # the 'signatures' feature needs prototypes to be updated.
388             signatures => sub {
389             my ($doc) = @_;
390              
391             # find all subs with prototypes
392             my $prototypes = $doc->find('PPI::Token::Prototype');
393             return unless $prototypes;
394              
395             # and turn them into prototype attributes
396             for my $proto (@$prototypes) {
397             $proto->insert_before( PPI::Token::Operator->new(':') );
398             $proto->insert_before(
399             PPI::Token::Attribute->new("prototype$proto") );
400             $proto->remove;
401             }
402             },
403              
404             # the 'fc' feature means CORE::fc is not required
405             fc => sub {
406             my ($doc) = @_;
407              
408             # find all occurences of 'CORE::fc'
409             my $core_fc = $doc->find(
410             sub {
411             my ( $root, $elem ) = @_;
412             return !!1
413             if $elem->isa('PPI::Token::Word') && $elem eq 'CORE::fc';
414             return !!0;
415             }
416             );
417             return unless $core_fc;
418              
419             # and replace them by 'fc'
420             $_->replace( PPI::Token::Word->new('fc') ) for @$core_fc;
421             },
422             },
423              
424             when_disabled => {
425              
426             # disabling the 'apostrophe_as_package_separator' feature
427             # drops support for apostrophe in package names
428             apostrophe_as_package_separator => sub {
429             my ($doc) = @_;
430              
431             # find all names with an apostrophe
432             my $apostrophes = $doc->find(
433             sub {
434             my ( $root, $elem ) = @_;
435             $elem->isa('PPI::Token::Word') && $elem =~ /'/;
436             }
437             );
438             return unless $apostrophes;
439              
440             # and replace it with double colons
441             for my $word (@$apostrophes) {
442             ( my $colon = "$word" ) =~ s/'/::/g;
443             $word->replace( bless { content => $colon },
444             'PPI::Token::Word' );
445             }
446             },
447             },
448              
449             );
450              
451             # PRIVATE "METHODS"
452              
453             # handle the case of CPAN modules that serve as compatibility layer for some
454             # features on older Perls, or that existed before the feature was developed
455             sub _handle_compat_modules {
456 9159     9159   31106 my ( $self, $doc ) = @_;
457 9159         26261 my $feature_in_bundle = $self->{feature_in_bundle};
458 9159         316194 for my $feature ( grep exists $feature{$_}{compat}, keys %feature ) {
459 64113         132817 for my $compat ( keys %{ $feature{$feature}{compat} } ) {
  64113         319551  
460 100749         229320 for my $include_compat ( _find_include( $compat => $doc ) ) {
461              
462             # handle `no $compat;`
463 1005 100       9510 if ( $include_compat->type eq 'no' ) {
464              
465             # if the feature is known and not disabled
466             # and the compat module has an unimport() sub
467 291 100 100     13036 if ( exists $feature_in_bundle->{known}{$feature}
      100        
468             && !exists $feature_in_bundle->{disabled}{$feature}
469             && $feature{$feature}{compat}{$compat} <= 0 )
470             {
471 21         182 my $no_feature = # feature enabled, and not disabled yet
472             PPI::Document->new( \"no feature '$feature';\n" );
473             $include_compat->insert_after( $_->remove )
474 21         34070 for $no_feature->elements;
475             }
476              
477             # some compat modules have no unimport() sub
478             # so we drop the useless `no $compat`
479             _drop_statement($include_compat)
480             if exists $feature_in_bundle->{known}{$feature}
481 291 100 66     7983 || $feature{$feature}{compat}{$compat} > 0;
482             }
483              
484             # handle `use $compat;`
485 1005 100       28502 if ( $include_compat->type eq 'use' ) {
486 714         16491 my $drop_stmt; # should we drop the old statement?
487              
488             # if the feature is known and not enabled or an unfeature
489             # and the compat module has an import() sub
490 714 100 100     9280 if ( exists $feature_in_bundle->{known}{$feature}
      100        
      66        
491             && ( !exists $feature_in_bundle->{enabled}{$feature}
492             || exists $feature{$feature}{unfeature} )
493             && $feature{$feature}{compat}{$compat} >= 0 )
494             {
495 108         950 my $use_feature =
496             PPI::Document->new( \"use feature '$feature';\n" );
497             $include_compat->insert_after( $_->remove )
498 108         176238 for $use_feature->elements;
499 108         24980 $drop_stmt++; # it's been replaced
500             }
501              
502             # backward compatibility features, like 'indirect',
503             # can be enabled before being known
504             # (also handle the unlikely case where there's no import())
505             $drop_stmt++
506             if !exists $feature{$feature}{unfeature}
507             && ( exists $feature_in_bundle->{enabled}{$feature}
508 714 100 66     11916 || $feature{$feature}{compat}{$compat} < 0 );
      66        
509              
510 714 100       4670 _drop_statement($include_compat) if $drop_stmt;
511             }
512             }
513             }
514             }
515             }
516              
517             sub _cleanup_bundled_features {
518 9159     9159   27504 my ( $self, $doc, $old_num ) = @_;
519 9159         39612 my $version_num = $self->version_num;
520 9159         24610 my $feature_in_bundle = $self->{feature_in_bundle};
521 9159         20058 my ( %enabled_in_code, %disabled_in_code );
522              
523             # drop features enabled in this bundle
524             # (also if they were enabled with `use experimental`)
525 9159         34221 for my $module (qw( feature experimental )) {
526 18318         669054 for my $use_line ( _find_include( $module => $doc, 'use' ) ) {
527 11118         557431 my @old_args = _ppi_list_to_perl_list( $use_line->arguments );
528 11118         62331 $enabled_in_code{$_}++ for @old_args;
529             my @new_args = # keep enabling features that
530             grep !exists $feature_in_bundle->{enabled}{$_} # are not enabled yet
531             || exists $feature{$_}{unfeature}, # or are unfeatures
532 11118   100     128540 grep exists $feature{$_}, # and actually exist
533             @old_args;
534 11118 100       52710 next if @new_args == @old_args; # nothing to change
535 7410 100       23540 if (@new_args) { # replace old statement with a smaller one
536 126         360 my $new_use_line = PPI::Document->new(
537 126         1471 \"use $module @{[ join ', ', map qq{'$_'}, @new_args]};" );
538             $use_line->insert_before( $_->remove )
539 126         176186 for $new_use_line->elements;
540 126         14082 $use_line->remove;
541             }
542 7284         24800 else { _drop_statement($use_line); }
543             }
544             }
545              
546             # deal with compat modules
547 9159         85459 $self->_handle_compat_modules($doc);
548              
549             # drop disabled features that are not part of the bundle
550             # (also if they were disabled with `no experimental`)
551 9159         90271 for my $module (qw( feature experimental )) {
552 18318         170854 for my $no_feature ( _find_include( $module => $doc, 'no' ) ) {
553 5547         160681 my @old_args = _ppi_list_to_perl_list( $no_feature->arguments );
554 5547         30259 $disabled_in_code{$_}++ for @old_args;
555             my @new_args = # keep disabling features
556             grep exists $feature{$_} # that actually exist and are
557 5547   100     46539 && !exists $feature_in_bundle->{disabled}{$_}, # not disabled yet
558             @old_args;
559 5547 100       24056 next if @new_args == @old_args; # nothing to change
560 591 100       2517 if (@new_args) { # replace old statement with a smaller one
561 45         156 my $new_no_feature = PPI::Document->new(
562 45         536 \"no $module @{[ join ', ', map qq{'$_'}, @new_args]};" );
563             $no_feature->insert_before( $_->remove )
564 45         72472 for $new_no_feature->elements;
565 45         5793 $no_feature->remove;
566             }
567 546         2501 else { _drop_statement($no_feature); }
568             }
569             }
570              
571             # apply some feature shine when crossing the feature enablement boundary
572 9159         26936 for my $feature ( sort keys %{ $feature_shine{when_enabled} } ) {
  9159         69883  
573 27477         162893 my $feature_enabled = $feature{$feature}{enabled};
574             $feature_shine{when_enabled}{$feature}->($doc)
575             if $old_num < $feature_enabled # code from before the feature
576             && $version_num >= $feature_enabled # bumped to after the feature
577             && !$enabled_in_code{$feature} # not enabling the feature
578 27477 100 100     234818 && !$disabled_in_code{$feature}; # and not disabling the feature
      100        
      100        
579             }
580              
581             # apply some feature shine when crossing the feature disablement boundary
582 9159         31349 for my $feature ( sort keys %{ $feature_shine{when_disabled} } ) {
  9159         42024  
583 9159         24931 my $feature_disabled = $feature{$feature}{disabled};
584             $feature_shine{when_disabled}{$feature}->($doc)
585             if $old_num < $feature_disabled # code from before the feature
586             && $version_num >= $feature_disabled # bumped to after the feature
587             && !$enabled_in_code{$feature} # not enabling the feature
588 9159 100 66     70965 && !$disabled_in_code{$feature}; # and not disabling the feature
      100        
      100        
589             }
590              
591             # drop experimental warnings, if any
592 9159         33374 for my $warn_line ( _find_include( warnings => $doc, 'no' ) ) {
593 894         29333 my @old_args = _ppi_list_to_perl_list( $warn_line->arguments );
594 894 100       7529 next unless grep /\Aexperimental::/, @old_args;
595             my @new_args = grep {
596 576         2786 ( my $feature = $_ ) =~ s/\Aexperimental:://;
  663         3069  
597 663         3461 !exists $feature_in_bundle->{enabled}{$feature};
598             }
599             grep /\Aexperimental::/, @old_args;
600 576         3009 my @keep_args = grep !/\Aexperimental::/, @old_args;
601 576 100 66     4272 next if @new_args == @old_args # nothing to remove
602             || @new_args + @keep_args == @old_args;
603 165 100 66     1237 if ( @new_args || @keep_args ) { # replace old statement
604 30         70 my $new_warn_line = PPI::Document->new(
605 30         317 \"no warnings @{[ join ', ', map qq{'$_'}, @new_args, @keep_args]};"
606             );
607             $warn_line->insert_before( $_->remove )
608 30         38432 for $new_warn_line->elements;
609 30         3219 $warn_line->remove;
610             }
611 135         511 else { _drop_statement($warn_line); }
612             }
613              
614             # strict is automatically enabled with 5.12
615 9159 100       68544 _drop_bare( use => strict => $doc ) if $version_num >= 5.012;
616              
617             # warnings are automatically enabled with 5.36
618 9159 100       92667 _drop_bare( use => warnings => $doc ) if $version_num >= 5.036;
619              
620 9159         77868 return;
621             }
622              
623             sub _insert_version_stmt {
624 9210     9210   35873 my ( $self, $doc, $old_num ) = @_;
625 9210   100     56714 $old_num //= 5.008;
626 9210         53175 my $version_stmt =
627             PPI::Document->new( \sprintf "use %s;\n", $self->version );
628 9210   100     12921351 my $insert_point = $doc->schild(0) // $doc->child(0);
629 9210 100       189486 return unless defined $insert_point; # empty document
630              
631             # record the indent before the next significant sibling
632             # (unless it's a version statement: it will be removed,
633             # and this version statement will replace it)
634 9159         19191 my $indent;
635 9159 100 100     49342 $indent = $insert_point->previous_sibling
      100        
      100        
636             if $insert_point->previous_sibling
637             && $insert_point->previous_sibling->isa('PPI::Token::Whitespace')
638             && !($insert_point->isa('PPI::Statement::Include') && $insert_point->version );
639              
640             # put the use VERSION LINE at the top of the file
641 9159 100       516104 if ( $insert_point->significant ) {
642 9108         51525 $insert_point->insert_before( $_->remove ) for $version_stmt->elements;
643 9108 100       2001927 $insert_point->insert_before( $indent->clone ) if $indent;
644             }
645             else {
646 51         176 $doc->add_element( $_->remove ) for $version_stmt->elements;
647             }
648              
649             # cleanup features enabled or disabled by the new version
650 9159         75648 _cleanup_bundled_features( $self, $doc, $old_num );
651             }
652              
653             sub _try_compile_file {
654 2778     2778   18446 my ( $file, $env ) = @_;
655 2778   50     44518 $env //= {};
656              
657             # redirect STDERR for quietness
658 2778         13718 my $tmperr = Path::Tiny->tempfile;
659 2778 50       2286827 open( \*OLDERR, '>&', \*STDERR ) or die "Can't dup STDERR: $!";
660 2778 50       23750 open( \*STDERR, '>', $tmperr ) or die "Can't re-open STDERR: $!";
661              
662             # setup a local environment
663 2778         603257 local %ENV = %ENV;
664 2778         21149 $ENV{$_} = $env->{$_} for keys %$env;
665              
666             # try to compile the file
667 2778         22267 my $status = system $^X, '-c', $file;
668 2778         1279151598 my $exit = $status >> 8;
669              
670             # get STDERR back, and warn about errors while compiling
671 2778 50       1115409 open( \*STDERR, '>&', \*OLDERR ) or die "Can't restore STDERR: $!";
672 2778 100       50196 warn $tmperr->slurp if $exit;
673              
674 2778         1310242 return !$exit; # 0 means success
675             }
676              
677             # PUBLIC METHOS
678              
679             sub bump_ppi {
680 10326     10326 1 2641317 my ( $self, $doc ) = @_;
681 10326         82957 $doc = $doc->clone;
682 10326   100     4814679 my $source = $doc->filename // 'input code';
683              
684             # found at least one version statement
685 10326 100       124942 if ( my @version_stmts = _version_stmts($doc) ) {
686              
687             # bail out if there's more than one `use VERSION`
688 3465 50       14132 if ( @version_stmts > 1 ) {
689 0         0 carp "Found multiple use VERSION statements in $source:"
690             . join ', ', map $_->version, @version_stmts;
691             }
692              
693             # drop the existing version statement
694             # and add the new one at the top
695             else {
696 3465         10109 my ($use_v) = _version_stmts($doc); # there's only one
697 3465         15864 my $old_num = version::->parse( $use_v->version )->numify;
698 3465 100       191021 if ( $old_num <= $self->version_num ) {
699 2349         18123 _insert_version_stmt( $self, $doc, $old_num );
700 2349         81376 _drop_statement( $use_v, !!1 );
701             }
702             }
703             }
704              
705             # no version statement found, add one
706 6861         39236 else { _insert_version_stmt( $self, $doc ); }
707              
708 10326         497619 return $doc;
709             }
710              
711             sub bump {
712 5882     5882 1 4224000 my ( $self, $code, $filename ) = @_;
713 5882         54235 my $doc = PPI::Document->new( \$code, filename => $filename );
714 5882   100     79981212 $filename //= 'input code';
715 5882 50       21564 croak "Parsing of $filename failed" unless defined $doc;
716 5882         27351 return $self->bump_ppi($doc)->serialize;
717             }
718              
719             sub bump_file {
720 2941     2941 1 11999402 my ( $self, $file ) = @_;
721 2941         15600 my $code = Path::Tiny->new($file)->slurp;
722 2941         815881 my $bumped = $self->bump( $code, $file );
723 2941 100       2402581 if ( $bumped ne $code ) {
724 2544         532000 $file->append( { truncate => 1 }, $bumped );
725 2544         1464065 return !!1;
726             }
727 397         383499 return !!0;
728             }
729              
730             # this one is private and returns an array ref with two values:
731             # the new PPI::Document, and the version it was actually bumped to
732             sub _bump_ppi_safely {
733 1275     1275   7462 my ( $self, $doc, $options ) = @_;
734 1275         7439 my $version_limit = $options->{version_limit};
735 1275   33     7031 $version_limit &&= stable_version($version_limit);
736 1275   33     10363 $version_limit //= do {
737 1275         16693 my @versions = map eval { version_fmt( $_->version ) },
  255         1585  
738             _version_stmts($doc);
739 1275   100     18460 $versions[0] // 5.010;
740             };
741              
742             # try compiling the file: if it fails, our safeguard won't work
743 1275   100     8403 my $source = $doc->filename // 'input code';
744 1275         37377 my $tmp = Path::Tiny->tempfile;
745 1275         1665531 $tmp->spew( $doc->serialize );
746 1275 100       2149031 unless ( _try_compile_file( $tmp, $options->{env} ) ) {
747 204         92339 warn "Can't bump Perl version safely for $source: it does not compile\n";
748 204         5483 return [ $doc->clone, undef ]; # undef means "didn't compile"
749             }
750              
751             # try bumping down version until it compiles
752 1071         592547 my $bumped_doc;
753 1071         20453 my $version = $self->version_num;
754 1071   100     18880 while ( $version >= $version_limit or $version = !!0 ) {
755 1503 100       10195 my $perv = $self->version_num eq $version
756             ? $self # no need to create a new object
757             : Perl::Version::Bumper->new( version => $version );
758 1503         10285 $bumped_doc = $perv->bump_ppi($doc);
759              
760             # try to compile the file
761 1503         149603 $tmp = Path::Tiny->tempfile;
762 1503         2637722 $tmp->spew( $bumped_doc->serialize );
763 1503 100       2577762 last if _try_compile_file( $tmp, $options->{env} );
764              
765             # bump version down and repeat
766 486         228440 $version = stable_version_dec($version);
767             }
768              
769 1071 100       612808 return $version ? [ $bumped_doc, $version ] : [ $doc->clone, $version ];
770             }
771              
772             sub bump_ppi_safely {
773 425     425 1 413484 my ( $self, $doc, $options ) = @_;
774 425         6193 return $self->_bump_ppi_safely( $doc, $options )->[0];
775             }
776              
777             sub bump_safely {
778 425     425 1 747223 my ( $self, $code, $options ) = @_;
779 425   50     6731 my $filename = $options->{filename} // 'input code';
780 425         9011 my $doc = PPI::Document->new( \$code, filename => $filename );
781 425 50       2467998 croak "Parsing of $filename failed" unless defined $doc;
782 425         6031 return $self->_bump_ppi_safely( $doc, $options )->[0]->serialize;
783             }
784              
785             sub bump_file_safely {
786 425     425 1 1405096 my ( $self, $file, $options ) = @_;
787 425         3833 my $doc = PPI::Document->new("$file"); # stringify any object
788 425 50       2121071 croak "Parsing of $file failed" unless defined $doc;
789             my ( $bumped_doc, $version ) =
790 425         1486 @{ $self->_bump_ppi_safely( $doc, $options ) };
  425         5504  
791 425 100       236612 Path::Tiny->new($file)->append( { truncate => 1 }, $bumped_doc->serialize )
792             if $version;
793 425         465291 return $version;
794             }
795              
796             1;
797              
798             =pod
799              
800             =head1 NAME
801              
802             Perl::Version::Bumper - Update C on any Perl code
803              
804             =head1 SYNOPSIS
805              
806             use Perl::Version::Bumper;
807              
808             my $perv = Perl::Version::Bumper->new( version => 'v5.36' );
809              
810             # bump a PPI::Document
811             my $bumped_ppi = $perv->bump_ppi($ppi_doc);
812              
813             # bump source code
814             my $bumped_code = $perv->bump($code);
815              
816             # bump the source of a file
817             $perv->bump_file($filename);
818              
819             # safe versions (check the result compiles)
820              
821             my $bumped_ppi = $perv->bump_ppi_safely($ppi_doc);
822             my $bumped_code = $perv->bump_safely($code);
823             $perv->bump_file_safely( $filename, $version_limit );
824              
825             =head1 DESCRIPTION
826              
827             C can update Perl code to make it declare it uses
828             a more recent version of the Perl language by way of C.
829              
830             It takes care of removing unnecessary loading of L and
831             L L, and adds the C line at the
832             top of the file (thus encouraging "line 1 semantics").
833              
834             It also manages the removal of "compatibility" modules when the feature
835             they provide a compatibility layer with is fully supported in the target
836             Perl version.
837              
838             If the code already declares a Perl version, it can only be bumped
839             to a higher version.
840              
841             The module L a few helper functions. These are mostly used
842             by support tools for this distribution, and are not meant for general use.
843              
844             =head1 CONSTRUCTOR
845              
846             =head2 new
847              
848             my $perv = Perl::Version::Bumper->new( %attributes );
849             my $perv = Perl::Version::Bumper->new( \%attributes );
850              
851             Return a new C object.
852              
853             =head1 ATTRIBUTES
854              
855             =head2 version
856              
857             The target version to bump to.
858              
859             Defaults to the stable version less than or equal to the version of the
860             currenly running C.
861              
862             The constructor accepts both forms of Perl versions, regular
863             (e.g. C) and floating-point (e.g. C<5.036>), and will
864             turn them into a string suitable for C.
865              
866             To protect against simple mistakes (e.g. passing C<5.36> instead of
867             C), the constructor does some sanity checking, and checks that
868             the given version:
869              
870             =over 4
871              
872             =item *
873              
874             is parsable as a Perl version number,
875              
876             =item *
877              
878             is greater than or equal to C,
879              
880             =item *
881              
882             is lower than the version of the Perl currently running,
883              
884             =item *
885              
886             is a stable Perl version.
887              
888             =back
889              
890             In case any of the above checks fail, the constructor will die.
891              
892             The constructor will also silently drop any sub-version information
893             (so C will be turned into C).
894              
895             =head1 CLASS METHODS
896              
897             =head2 feature_version
898              
899             Return the version (in numeric format) of the feature set recognized
900             by this module. It is not possible to bump code over that version.
901              
902             The current value of C is: C<5.042>.
903              
904             =head2 feature_data
905              
906             Return a I of the internal data structure containing all the
907             information about features. That should only be needed for testing
908             and debugging.
909              
910             =head1 METHODS
911              
912             =head2 version_num
913              
914             Return the L attribute as a number.
915              
916             =head2 bump_ppi
917              
918             my $bumped_ppi_doc = $perv->bump_ppi($ppi_doc);
919              
920             Take a L as input, and return a I L
921             with its declared version bumped to L.
922              
923             =head2 bump
924              
925             my $bumped_code = $perv->bump($code);
926              
927             Take a string containing Perl code as input, bump the declared Perl
928             version in the source code to L, and return the new source
929             code as a string.
930              
931             =head2 bump_file
932              
933             $perv->bump_file($filename);
934              
935             Bump the code of the file argument in-place.
936              
937             Return a boolean indicating if the file content was modified or not.
938              
939             =head1 SAFE METHODS
940              
941             The L, L and L methods previously described
942             modify the source code they're given, but give I that the
943             updated code will even compile.
944              
945             To address this issue, L, L and
946             L methods work as the regular methods, but will only
947             produce code that actually compiles.
948              
949             If all attempts fail, the return value is identical to the input value.
950              
951             =head2 Example of a safe bump
952              
953             The following code uses L:
954              
955             my %h; $h{ 1, 2 } = 3; # same as $foo{"1\x{1c}2"} = 3;
956              
957             L will produce the following when trying to update it to C:
958              
959             use v5.40;
960             my %h; $h{ 1, 2 } = 3; # same as $foo{"1\x{1c}2"} = 3;
961              
962             Which fails to compile with the following error:
963              
964             Multidimensional hash lookup is disabled
965              
966             It's not possible to just bump this code up to C and expect it to
967             work, because it uses multidimensional array emulation, and the feature
968             that represents this (C) was disabled in C.
969             This code will in fact fail to compile with all version bundles greater
970             or equal to C.
971              
972             A I to try to bump this code to C is to try with
973             C, detect it fails to compile, try again with C and
974             C, which also fail, until we hit C which compiles just
975             fine (because the C feature is still enabled in that
976             bundle). Leaving us with the following code:
977              
978             use v5.34;
979             my %h; $h{ 1, 2 } = 3; # same as $foo{"1\x{1c}2"} = 3;
980              
981             The code needs to be updated to I use multidimensional array emulation
982             before it can I be bumped past version C.
983              
984             =head2 Process of a safe bump
985              
986             The process for a safe bump is to take some input, and try to compile it.
987             If the compilation fails, return immediately.
988              
989             Otherwise, continue with the process: bump the content, and try to
990             compile the result. Return as soon as compilation succeeds.
991              
992             If compilation fails, decrease the target Perl version number, bump
993             the content to that version, and try to compile the result again. Keep
994             decreasing the target version, all the way back to the currently
995             declared version in the document, or L, whichever is more
996             recent. Give up after the last compilation failure.
997              
998             =head2 Options for a safe bump
999              
1000             All the methods below take one input argument (a L,
1001             a string of code or a filename) and one optional hash reference
1002             for options.
1003              
1004             The possible options are:
1005              
1006             =over 4
1007              
1008             =item version_limit
1009              
1010             The version at which to stop decreasing the target version.
1011             Defaults to C.
1012              
1013             =item env
1014              
1015             A hash reference of key/value pairs for environment variables
1016             to be set when trying to compile the bumped code.
1017              
1018             =back
1019              
1020             =head2 bump_ppi_safely
1021              
1022             my $bumped_ppi = $perv->bump_ppi_safely( $ppi_doc, \%options );
1023              
1024             Safely bump the source code in the given L.
1025              
1026             The return value is a new L containing the result of the
1027             "safe bump" (its content might be the same as the original if there's
1028             no safe way to bump the code).
1029              
1030             =head2 bump_safely
1031              
1032             my $bumped_code = $perv->bump_safely( $code, \%options );
1033             my ( $bumped_code, $new_version ) = $perv->bump_safely($code);
1034              
1035             Safely bump the source code given as a string.
1036              
1037             The return value is a string containing the new source code.
1038              
1039             =head2 bump_file_safely
1040              
1041             $perv->bump_file_safely( $filename, \%options );
1042              
1043             Safely bump the code in the file argument in-place. The file will
1044             not be modified if the code can't be bumped safely.
1045              
1046             The return value is C if the original didn't compile, false
1047             if all attempts to bump the file failed, and the actual (numerical)
1048             version number the file was bumped to in case of success.
1049              
1050             =head1 EXPORTS
1051              
1052             The following I can be optionally exported. Be aware that they
1053             are mostly meant for internal use of the module and helper scripts.
1054              
1055             =head2 version_fmt
1056              
1057             my $v = version_fmt( $version );
1058              
1059             Return the given version (in string, v-string or float format) as a number.
1060              
1061             This function will die if the given version is not a plausible Perl
1062             version number, i.e. is strictly lower than C<5.010>.
1063              
1064             Note that all the following functions start by normalizing their
1065             argument by calling L, meaning they will die in the same
1066             circumstances.
1067              
1068             =head2 version_use
1069              
1070             my $v = version_use( $version );
1071              
1072             Return the given version (in string, v-string or float format) as
1073             a string suitable for a C line.
1074              
1075             =head2 stable_version
1076              
1077             my $s = stable_version( $version );
1078              
1079             Return the closest stable version lower or equal to the given version,
1080             as a number.
1081              
1082             =head2 stable_version_inc
1083              
1084             my $n = stable_version_inc( $version );
1085              
1086             Return the stable version following the given version, as a number.
1087              
1088             =head2 stable_version_dec
1089              
1090             my $p = stable_version_dec( $version );
1091              
1092             Return the stable version preceding the given version, as a number.
1093              
1094             =head1 VERSION UPGRADE ALGORITHM
1095              
1096             For a given version number, a feature has three attributes:
1097              
1098             =over 4
1099              
1100             =item known
1101              
1102             the B I knows about the feature starting from that version.
1103              
1104             If it's not known, passing it to C will I during
1105             compilation with C (where
1106             5.x.y is the version of the binary C program).
1107              
1108             =item enabled
1109              
1110             the feature is enabled starting with the corresponding I bundle
1111             (i.e. C will implicitely enable it).
1112              
1113             =item disabled
1114              
1115             the feature is disabled starting from the corresponding I bundle
1116             (i.e. C will implicitely disable it).
1117              
1118             This is the case for so-called "unfeatures", i.e. constructs that were
1119             deemed undesirable and removed from the language (e.g. C,
1120             C, etc.).
1121              
1122             =item removed
1123              
1124             the feature was removed starting from the given version.
1125              
1126             The only feature that was removed so far is C (in Perl v5.30).
1127              
1128             =back
1129              
1130             If there is more than one C line in the file, the algorithm
1131             will bail out. Otherwise, the previous C line will be
1132             removed, and a new one added at the top of the file (line 1).
1133              
1134             The features that were enabled via C and are part of the
1135             C feature bundle will be removed from the corresponding C
1136             feature> or C lines. The disabling of the corresponding
1137             C warnings will be removed.
1138              
1139             "Unfeatures" are treated differently. Unfeatures are features that were
1140             created to represent historical Perl behaviour, and are considered enabled
1141             by default in all bundles until they are disabled at a later stage. If an
1142             unfeature is enabled, it is considered to be for documentation purposes
1143             (to indicate that the undesirable historical feature was used), and
1144             therefore not removed, even if the specified C enables it.
1145              
1146             The (un)features that were disabled via C and are disabled
1147             as part of the C feature bundle will be removed from the
1148             corresponding C or C lines.
1149              
1150             If compatibility modules (CPAN modules that provide support for the
1151             feature in older Perls) were loaded, they will removed if the feature
1152             is enabled in the feature bundle for C, or replaced by the
1153             corresponding C if the feature is known by the corresponding
1154             C binary but not yet enabled by the feature bundle. (In the context
1155             of compatibility modules for unfeatures, the same consideration for
1156             documentation purposes apply.)
1157              
1158             When a feature is enabled (or disabled) in the context of a feature
1159             version bundle that's less than the version when the feature was known
1160             by Perl, the line won't be removed.
1161              
1162             For example this line:
1163              
1164             use feature 'signatures';
1165              
1166             will die with any perl before perl5.20.0, because the binary does not
1167             know about the feature itself.
1168              
1169             When writing code like this:
1170              
1171             use v5.10;
1172             use feature 'signatures';
1173              
1174             one is opting into a version of the Perl language that is not described
1175             by any specific feature bundle. However, any perl that knows about the
1176             C feature will know how to run it.
1177              
1178             Bumping it to the feature bundle for v5.16, for example, is valid,
1179             and will work with any B that knows about the C feature:
1180              
1181             use v5.16;
1182             use feature 'signatures';
1183              
1184             And so on until v5.36, when the C feature was enabled by
1185             the corresponding version bundle:
1186              
1187             use v5.36;
1188              
1189             Finally, some features may imply extra edits:
1190              
1191             =over 4
1192              
1193             =item bitwise
1194              
1195             When the C feature is enabled, the behaviour of the bitwise
1196             operators (C<&>, C<|>, C<~> and C<^>) is modified. If the code makes use
1197             of one of them, and the code is moved from a version I v5.28
1198             to a version greater or equal to v5.28, the C feature will
1199             be I, and a comment will be added, asking the maintainer to
1200             review their use according to the C feature before removing it.
1201              
1202             =item signatures
1203              
1204             When signatures are implicitely enabled, any prototypes will be rewritten
1205             with the prototype attribute syntax. For example:
1206              
1207             sub foo ($@) { ... }
1208              
1209             will become:
1210              
1211             sub foo :prototype($@) { ... }
1212              
1213             =item fc
1214              
1215             Once C is implicitely enabled, All uses of C will be
1216             replaced by a bare C.
1217              
1218             =back
1219              
1220             =head2 Feature/version data table
1221              
1222             The following table is used to generate the feature data hash.
1223              
1224             It is generated using the C script
1225             shipped with the distribution.
1226              
1227             The keys are:
1228              
1229             =over 4
1230              
1231             =item known
1232              
1233             when perl first learnt about the feature
1234              
1235             =item enabled
1236              
1237             when the feature was first enabled (may be before it was known)
1238              
1239             =item disabled
1240              
1241             when the feature was first disabled
1242              
1243             =item compat
1244              
1245             replacement modules for features to be deprecated / added
1246              
1247             =back
1248              
1249             Different features have different lifecycles:
1250              
1251             =over 4
1252              
1253             =item *
1254              
1255             New features (i.e. additional behaviour that didn't exist in Perl v5.8):
1256              
1257             =over 4
1258              
1259             =item *
1260              
1261             are C in the Perl release that introduced them
1262              
1263             =item *
1264              
1265             are C either in the same version (e.g. C, C)
1266             or after an "experimental" phase (e.g. C, C)
1267              
1268             =item *
1269              
1270             once enabled, they are not meant to be C in a later bundle.
1271              
1272             =back
1273              
1274             =item *
1275              
1276             Unfeatures, or backwards compatibility features (features that existed
1277             in older Perls, but were later deemed undesirable, and scheduled for
1278             being eventually disabled or removed):
1279              
1280             =over 4
1281              
1282             =item *
1283              
1284             are C in the C<:default> bundle (they were part of the old
1285             Perl 5 behaviour) before they are even C (a feature that
1286             represents them was added to Perl).
1287              
1288             =item *
1289              
1290             are meant to be manually disabled (with C), until a
1291             later feature bundle eventually disables them by default.
1292              
1293             =back
1294              
1295             =back
1296              
1297             "compat" modules are CPAN modules meant to add support to the feature on
1298             perls where it's not available yet. They exist both for new features and
1299             backwards compatibility features. The number following the module name in
1300             the data structure below is the sum of 1 (if the module has an C
1301             method) and -1 (if the module has an C method).
1302              
1303             =cut
1304              
1305             BEGIN {
1306 6     6   398 $FEATURE_DATA = << '=cut';
1307              
1308             =pod
1309              
1310             5.042 features known enabled disabled removed compat
1311             say 5.010 5.010 Perl6::Say 1 Say::Compat 1
1312             state 5.010 5.010
1313             switch 5.010 5.010 5.036
1314             unicode_strings 5.012 5.012
1315             array_base 5.016 5.010 5.016 5.030
1316             current_sub 5.016 5.016
1317             evalbytes 5.016 5.016
1318             fc 5.016 5.016
1319             unicode_eval 5.016 5.016
1320             lexical_subs 5.018 5.026
1321             postderef 5.020 5.024
1322             postderef_qq 5.020 5.024
1323             signatures 5.020 5.036
1324             bitwise 5.022 5.028
1325             refaliasing 5.022
1326             declared_refs 5.026
1327             indirect 5.032 5.010 5.036 indirect 0
1328             isa 5.032 5.036
1329             multidimensional 5.034 5.010 5.036 multidimensional 0
1330             bareword_filehandles 5.034 5.010 5.038 bareword::filehandles 0
1331             try 5.034 5.040 Feature::Compat::Try 1 Syntax::Feature::Try 0 Syntax::Keyword::Try 0
1332             defer 5.036 Feature::Compat::Defer 1 Syntax::Keyword::Defer 0
1333             extra_paired_delimiters 5.036
1334             module_true 5.038 5.038
1335             class 5.038 Feature::Compat::Class 1
1336             apostrophe_as_package_separator 5.042 5.010 5.042
1337             smartmatch 5.042 5.010 5.042
1338             keyword_all 5.042
1339             keyword_any 5.042
1340              
1341             =cut
1342              
1343             }
1344              
1345             =head1 ADDITIONAL INFORMATION ABOUT PERL FEATURES AND CONSTRUCTS
1346              
1347             =head2 Official documentation
1348              
1349             =over 4
1350              
1351             =item L
1352              
1353             Perl pragma to enable new features.
1354              
1355             =item L
1356              
1357             A listing of experimental features in Perl.
1358              
1359             =item L
1360              
1361             This pragma provides an easy and convenient way to enable or disable
1362             experimental features.
1363              
1364             =back
1365              
1366             =head2 CPAN Modules
1367              
1368             =over 4
1369              
1370             =item L
1371              
1372             For some new syntactic constructs, there is the L.
1373             For the rest, there is L.::
1374              
1375             =item L
1376              
1377             Find a minimum required version of C for Perl code.
1378              
1379             =item L
1380              
1381             L is an alternative fast & lightweight
1382             implementation of L.
1383              
1384             =back
1385              
1386             =head2 Other
1387              
1388             =over 4
1389              
1390             =item L
1391              
1392             The most significant features introduced for recent versions of the Perl
1393             scripting language.
1394              
1395             =back
1396              
1397             =head1 ACKNOWLEDGMENT
1398              
1399             This software was originally developed at Booking.com. With approval
1400             from Booking.com, this software was released as open source, for which
1401             the authors would like to express their gratitude.
1402              
1403             =head1 AUTHOR
1404              
1405             Philippe Bruhat (BooK)
1406              
1407             =head1 COPYRIGHT
1408              
1409             Copyright 2024-2026 Philippe Bruhat (BooK), all rights reserved.
1410              
1411             =head1 LICENSE
1412              
1413             This program is free software; you can redistribute it and/or modify it
1414             under the same terms as Perl itself.
1415              
1416             =cut