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 66     66   467 use strict;
  66         255  
  66         3222  
48              
49 66     66   31296 use version 0.77 ();
  66         156831  
  66         3021  
50 66     66   37177 use Safe::Isa '$_call_if_object';
  66         46820  
  66         10149  
51              
52 66     66   570 use PPI::Statement ();
  66         146  
  66         1728  
53 66     66   35961 use PPI::Statement::Include::Perl6 ();
  66         323  
  66         104218  
54              
55             our $VERSION = '1.28401'; # TRIAL
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 3322     3322 1 12428 my $self = shift;
72 3322 50       14614 my $keyword = $self->schild(0) or return undef;
73 3322 50       19915 $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 3289     3289 1 6203 my $self = shift;
105 3289 100       8869 my $module = $self->schild(1) or return undef;
106 3287 100       17504 $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 986 my $self = shift;
120 10         44 my $argument = $self->schild(3);
121 10 100 100     95 if ( $argument and $argument->isa('PPI::Token::Operator') ) {
122 1         5 return undef;
123             }
124              
125 9 50       29 my $version = $self->schild(2) or return undef;
126 9 100       64 return undef unless $version->isa('PPI::Token::Number');
127              
128 6         37 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 380 my $self = shift;
157 2 50       9 my $module = $self->module or return '';
158 2 50       31 $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 3303     3303 1 7300 my $self = shift;
182 3303 100       11123 my $version = $self->schild(1) or return undef;
183 3301 100       27800 $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 1031 my $self = shift;
198 11 50       50 my $version = $self->schild(1) or return undef;
199 11 100       88 $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 699 my $self = shift;
216 22         89 my @args = $self->schildren;
217              
218             # Remove the "use", "no" or "require"
219 22         60 shift @args;
220              
221             # Remove the statement terminator
222 22 100 66     128 if (
223             $args[-1]->isa('PPI::Token::Structure')
224             and
225             $args[-1]->content eq ';'
226             ) {
227 21         40 pop @args;
228             }
229              
230             # Remove the module or perl version.
231 22         41 shift @args;
232              
233 22 100       56 return unless @args;
234              
235 20 100       100 if ( $args[0]->isa('PPI::Token::Number') ) {
236 2 100       9 my $after = $args[1] or return;
237 1 50       6 $after->isa('PPI::Token::Operator') or shift @args;
238             }
239              
240 19         53 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 3315     3315 1 9492 my ($self) = @_;
261 3315         12604 my $type = $self->type;
262 3315 100       10242 return if $type eq "require";
263              
264 3293 100       12284 if ( my $cb_features = $self->_custom_feature_include_cb->($self) ) #
265 1         12 { return $cb_features; }
266              
267 3292 100       18472 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 30 100       712 return { signatures => "perl" }
274             if version::->parse($perl_version) >= 5.035;
275             }
276              
277 3286 100       10992 my $module = $self->module or return;
278              
279 3257         17289 my %known = ( signatures => 1, try => 1 );
280 3257         7963 my $on_or_off = $type eq "use";
281              
282 3257 100 100     19332 if ( $on_or_off
283             and my $custom = $self->_custom_feature_includes->{ $module } ) #
284 2         13 { return $custom; }
285              
286 3255 100       27399 if ( $module eq "feature" ) {
    100          
    100          
    100          
    100          
287 12         39 my @features = grep $known{$_}, $self->_decompose_arguments;
288 12 100       117 return { map +( $_ => $on_or_off ? "perl" : 0 ), @features };
289             }
290             elsif ( $module eq "Mojolicious::Lite" ) {
291 1         6 my $wants_signatures = grep /-signatures/, $self->_decompose_arguments;
292 1 50       11 return { signatures => $wants_signatures ? "perl" : 0 };
293             }
294             elsif ( $module eq "Modern::Perl" ) {
295 1   50     5 my $v = $self->module_version->$_call_if_object("literal") || 0;
296 1 50       13 return { signatures => $v >= 2023 ? "perl" : 0 };
297             }
298             elsif ( $module eq "experimental" ) {
299 1         6 my $wants_signatures = grep /signatures/, $self->_decompose_arguments;
300 1 50       32 return { signatures => $wants_signatures ? "perl" : 0 };
301             }
302             elsif ( $module eq "Syntax::Keyword::Try" ) {
303 7 50       50 return { try => $on_or_off ? "Syntax::Keyword::Try" : 0 };
304             }
305              
306 3233         28400 return;
307             }
308              
309             sub _decompose_arguments {
310 14     14   28 my ($self) = @_;
311 14         36 my @args = $self->arguments;
312 14         49 while ( grep ref, @args ) {
313 16         67 @args = map $self->_decompose_argument($_), @args;
314             }
315 14         93 return @args;
316             }
317              
318             sub _decompose_argument {
319 18     18   43 my ( $self, $arg ) = @_;
320 18 100 100     139 return $arg->children
321             if $arg->isa("PPI::Structure::List")
322             or $arg->isa("PPI::Statement::Expression");
323 16   100     120 my $as_text = $arg->can("literal") || $arg->can("string");
324 16 100       95 return $as_text->($arg) if $as_text;
325 1 50 33     9 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 2244     2244   5926 my ($self) = @_;
334             return unless #
335 2244 50       6224 my $document = $self->document;
336 2244   100     9341 return $document->custom_feature_includes || {};
337             }
338              
339             sub _custom_feature_include_cb {
340 3293     3293   8548 my ($self) = @_;
341             return unless #
342 3293 50       12970 my $document = $self->document;
343 3293   66 3292   14675 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