File Coverage

blib/lib/PPI/Statement/Include.pm
Criterion Covered Total %
statement 87 89 97.7
branch 64 78 82.0
condition 20 25 80.0
subroutine 18 18 100.0
pod 8 8 100.0
total 197 218 90.3


line stmt bran cond sub pod time code
1             package PPI::Statement::Include;
2              
3             =pod
4              
5             =head1 NAME
6              
7             PPI::Statement::Include - Statements that include other code
8              
9             =head1 SYNOPSIS
10              
11             # The following are all includes
12             use 5.006;
13             use strict;
14             use My::Module;
15             use constant FOO => 'Foo';
16             require Foo::Bar;
17             require "Foo/Bar.pm";
18             require $foo if 1;
19             no strict 'refs';
20              
21             =head1 INHERITANCE
22              
23             PPI::Statement::Include
24             isa PPI::Statement
25             isa PPI::Node
26             isa PPI::Element
27              
28             =head1 DESCRIPTION
29              
30             Despite its name, the C class covers a number
31             of different types of statement that cover all statements starting with
32             C, C and C.
33              
34             But basically, they cover three situations.
35              
36             Firstly, a dependency on a particular version of perl (for which the
37             C method returns true), a pragma (for which the C method
38             returns true), or the loading (and unloading via no) of modules.
39              
40             =head1 METHODS
41              
42             C has a number of methods in addition to the standard
43             L, L and L methods.
44              
45             =cut
46              
47 68     68   350 use strict;
  68         120  
  68         2368  
48              
49 68     68   22103 use version 0.77 ();
  68         108787  
  68         2234  
50 68     68   28074 use Safe::Isa '$_call_if_object';
  68         32585  
  68         6923  
51              
52 68     68   381 use PPI::Statement ();
  68         107  
  68         833  
53 68     68   26953 use PPI::Statement::Include::Perl6 ();
  68         165  
  68         68475  
54              
55             our $VERSION = '1.291';
56              
57             our @ISA = "PPI::Statement";
58              
59             =pod
60              
61             =head2 type
62              
63             The C method returns the general type of statement (C<'use'>, C<'no'>
64             or C<'require'>).
65              
66             Returns the type as a string, or C if the type cannot be detected.
67              
68             =cut
69              
70             sub type {
71 3347     3347 1 8250 my $self = shift;
72 3347 50       9285 my $keyword = $self->schild(0) or return undef;
73 3347 50       11354 $keyword->isa('PPI::Token::Word') and $keyword->content;
74             }
75              
76             =pod
77              
78             =head2 module
79              
80             The C method returns the module name specified in any include
81             statement. This C pragma names, because pragma are implemented
82             as modules. (And lets face it, the definition of a pragma can be fuzzy
83             at the best of times in any case)
84              
85             This covers all of these...
86              
87             use strict;
88             use My::Module;
89             no strict;
90             require My::Module;
91              
92             ...but does not cover any of these...
93              
94             use 5.006;
95             require 5.005;
96             require "explicit/file/name.pl";
97              
98             Returns the module name as a string, or C if the include does
99             not specify a module name.
100              
101             =cut
102              
103             sub module {
104 3312     3312 1 4317 my $self = shift;
105 3312 100       5351 my $module = $self->schild(1) or return undef;
106 3310 100       9807 $module->isa('PPI::Token::Word') and $module->content;
107             }
108              
109             =pod
110              
111             =head2 module_version
112              
113             The C method returns the minimum version of the module
114             required by the statement, if there is one.
115              
116             =cut
117              
118             sub module_version {
119 10     10 1 580 my $self = shift;
120 10         29 my $argument = $self->schild(3);
121 10 100 100     55 if ( $argument and $argument->isa('PPI::Token::Operator') ) {
122 1         3 return undef;
123             }
124              
125 9 50       13 my $version = $self->schild(2) or return undef;
126 9 100       1818 return undef unless $version->isa('PPI::Token::Number');
127              
128 6         23 return $version;
129             }
130              
131             =pod
132              
133             =head2 pragma
134              
135             The C method checks for an include statement's use as a
136             pragma, and returns it if so.
137              
138             Or at least, it claims to. In practice it's a lot harder to say exactly
139             what is or isn't a pragma, because the definition is fuzzy.
140              
141             The C of a pragma is to modify the way in which the parser works.
142             This is done though the use of modules that do various types of internals
143             magic.
144              
145             For now, PPI assumes that any "module name" that is only a set of
146             lowercase letters (and perhaps numbers, like C). This
147             behaviour is expected to change, most likely to something that knows
148             the specific names of the various "pragmas".
149              
150             Returns the name of the pragma, or false ('') if the include is not a
151             pragma.
152              
153             =cut
154              
155             sub pragma {
156 2     2 1 256 my $self = shift;
157 2 50       6 my $module = $self->module or return '';
158 2 50       17 $module =~ /^[a-z][a-z\d]*$/ ? $module : '';
159             }
160              
161             =pod
162              
163             =head2 version
164              
165             The C method checks for an include statement that introduces a
166             dependency on the version of C the code is compatible with.
167              
168             This covers two specific statements.
169              
170             use 5.006;
171             require 5.006;
172              
173             Currently the version is returned as a string, although in future the version
174             may be returned as a L object. If you want a numeric representation,
175             use C. Returns false if the statement is not a version
176             dependency.
177              
178             =cut
179              
180             sub version {
181 3328     3328 1 4967 my $self = shift;
182 3328 100       5878 my $version = $self->schild(1) or return undef;
183 3326 100       17301 $version->isa('PPI::Token::Number') ? $version->content : '';
184             }
185              
186             =pod
187              
188             =head2 version_literal
189              
190             The C method has the same behavior as C, but the
191             version is returned as a numeric literal. Returns false if the statement is
192             not a version dependency.
193              
194             =cut
195              
196             sub version_literal {
197 11     11 1 582 my $self = shift;
198 11 50       34 my $version = $self->schild(1) or return undef;
199 11 100       93 $version->isa('PPI::Token::Number') ? $version->literal : '';
200             }
201              
202             =pod
203              
204             =head2 arguments
205              
206             The C method gives you the rest of the statement after the
207             module/pragma and module version, i.e. the stuff that will be used to
208             construct what gets passed to the module's C subroutine. This does
209             include the comma, etc. operators, but doesn't include non-significant direct
210             children or any final semicolon.
211              
212             =cut
213              
214             sub arguments {
215 22     22 1 590 my $self = shift;
216 22         60 my @args = $self->schildren;
217              
218             # Remove the "use", "no" or "require"
219 22         30 shift @args;
220              
221             # Remove the statement terminator
222 22 100 66     85 if (
223             $args[-1]->isa('PPI::Token::Structure')
224             and
225             $args[-1]->content eq ';'
226             ) {
227 21         30 pop @args;
228             }
229              
230             # Remove the module or perl version.
231 22         28 shift @args;
232              
233 22 100       35 return unless @args;
234              
235 20 100       62 if ( $args[0]->isa('PPI::Token::Number') ) {
236 2 100       7 my $after = $args[1] or return;
237 1 50       5 $after->isa('PPI::Token::Operator') or shift @args;
238             }
239              
240 19         36 return @args;
241             }
242              
243             =head2 feature_mods
244              
245             # `use feature 'signatures';`
246             my %mods = $include->feature_mods;
247             # { signatures => "perl" }
248              
249             # `use 5.036;`
250             my %mods = $include->feature_mods;
251             # { signatures => "perl" }
252              
253             Returns a hashref of features identified as enabled by the include, or undef if
254             the include does not enable features. The value for each feature indicates the
255             provider of the feature.
256              
257             =cut
258              
259             sub feature_mods {
260 3340     3340 1 5462 my ($self) = @_;
261 3340         8109 my $type = $self->type;
262 3340 100       6649 return if $type eq "require";
263              
264 3318 100       7956 if ( my $cb_features = $self->_custom_feature_include_cb->($self) ) #
265 1         6 { return $cb_features; }
266              
267 3317 100       12285 if ( my $perl_version = $self->version ) {
268             ## tried using feature.pm, but it is impossible to install future
269             ## versions of it, so e.g. a 5.20 install cannot know about
270             ## 5.36 features
271              
272             # crude proof of concept hack due to above
273 32 100       533 return { signatures => "perl" }
274             if version::->parse($perl_version) >= 5.035;
275             }
276              
277 3309 100       7312 my $module = $self->module or return;
278              
279 3280         10410 my %known = ( signatures => 1, try => 1 );
280 3280         5578 my $on_or_off = $type eq "use";
281              
282 3280 100 100     9401 if ( $on_or_off
283             and my $custom = $self->_custom_feature_includes->{ $module } ) #
284 2         6 { return $custom; }
285              
286 3278 100       13411 if ( $module eq "feature" ) {
    100          
    100          
    100          
    100          
287 12         23 my @features = grep $known{$_}, $self->_decompose_arguments;
288 12 100       63 return { map +( $_ => $on_or_off ? "perl" : 0 ), @features };
289             }
290             elsif ( $module eq "Mojolicious::Lite" ) {
291 1         4 my $wants_signatures = grep /-signatures/, $self->_decompose_arguments;
292 1 50       6 return { signatures => $wants_signatures ? "perl" : 0 };
293             }
294             elsif ( $module eq "Modern::Perl" ) {
295 1   50     16 my $v = $self->module_version->$_call_if_object("literal") || 0;
296 1 50       6 return { signatures => $v >= 2023 ? "perl" : 0 };
297             }
298             elsif ( $module eq "experimental" ) {
299 1         4 my $wants_signatures = grep /signatures/, $self->_decompose_arguments;
300 1 50       7 return { signatures => $wants_signatures ? "perl" : 0 };
301             }
302             elsif ( $module eq "Syntax::Keyword::Try" ) {
303 7 50       29 return { try => $on_or_off ? "Syntax::Keyword::Try" : 0 };
304             }
305              
306 3256         11057 return;
307             }
308              
309             sub _decompose_arguments {
310 14     14   20 my ($self) = @_;
311 14         33 my @args = $self->arguments;
312 14         39 while ( grep ref, @args ) {
313 16         32 @args = map $self->_decompose_argument($_), @args;
314             }
315 14         45 return @args;
316             }
317              
318             sub _decompose_argument {
319 18     18   29 my ( $self, $arg ) = @_;
320 18 100 100     87 return $arg->children
321             if $arg->isa("PPI::Structure::List")
322             or $arg->isa("PPI::Statement::Expression");
323 16   100     86 my $as_text = $arg->can("literal") || $arg->can("string");
324 16 100       43 return $as_text->($arg) if $as_text;
325 1 50 33     5 return if $arg->isa("PPI::Token::Operator")
326             or $arg->content eq ",";
327 0         0 warn "possibly unrecognized feature because of unknown arg decompose"
328             . " type: '$arg' : " . ref $arg;
329 0         0 return;
330             }
331              
332             sub _custom_feature_includes {
333 2267     2267   3518 my ($self) = @_;
334             return unless #
335 2267 50       4283 my $document = $self->document;
336 2267   100     4951 return $document->custom_feature_includes || {};
337             }
338              
339             sub _custom_feature_include_cb {
340 3318     3318   4928 my ($self) = @_;
341             return unless #
342 3318 50       7955 my $document = $self->document;
343 3318   66 3317   9744 return $document->custom_feature_include_cb || sub { };
344             }
345              
346             1;
347              
348             =pod
349              
350             =head1 TO DO
351              
352             - Write specific unit tests for this package
353              
354             =head1 SUPPORT
355              
356             See the L in the main module.
357              
358             =head1 AUTHOR
359              
360             Adam Kennedy Eadamk@cpan.orgE
361              
362             =head1 COPYRIGHT
363              
364             Copyright 2001 - 2011 Adam Kennedy.
365              
366             This program is free software; you can redistribute
367             it and/or modify it under the same terms as Perl itself.
368              
369             The full text of the license can be found in the
370             LICENSE file included with this module.
371              
372             =cut