File Coverage

blib/lib/Perl/Critic/Utils/PPI.pm
Criterion Covered Total %
statement 68 84 80.9
branch 42 68 61.7
condition 10 21 47.6
subroutine 15 17 88.2
pod 10 10 100.0
total 145 200 72.5


line stmt bran cond sub pod time code
1             package Perl::Critic::Utils::PPI;
2              
3 40     40   126364 use 5.010001;
  40         164  
4 40     40   231 use strict;
  40         95  
  40         840  
5 40     40   212 use warnings;
  40         94  
  40         1023  
6              
7 40     40   744 use Readonly;
  40         4519  
  40         1901  
8              
9 40     40   258 use Scalar::Util qw< blessed readonly >;
  40         85  
  40         1926  
10              
11 40     40   248 use Exporter 'import';
  40         129  
  40         46572  
12              
13             our $VERSION = '1.146';
14              
15             #-----------------------------------------------------------------------------
16              
17             our @EXPORT_OK = qw(
18             is_ppi_expression_or_generic_statement
19             is_ppi_generic_statement
20             is_ppi_statement_subclass
21             is_ppi_simple_statement
22             is_ppi_constant_element
23             is_subroutine_declaration
24             is_in_subroutine
25             get_constant_name_element_from_declaring_statement
26             get_next_element_in_same_simple_statement
27             get_previous_module_used_on_same_line
28             );
29              
30             our %EXPORT_TAGS = (
31             all => \@EXPORT_OK,
32             );
33              
34             #-----------------------------------------------------------------------------
35              
36             sub is_ppi_expression_or_generic_statement {
37 638     638 1 3415 my $element = shift;
38              
39 638 100       2665 return if not $element;
40 637 100       2108 return if not $element->isa('PPI::Statement');
41 636 100       2376 return 1 if $element->isa('PPI::Statement::Expression');
42              
43 254         734 my $element_class = blessed($element);
44              
45 254 50       598 return if not $element_class;
46 254         907 return $element_class eq 'PPI::Statement';
47             }
48              
49             #-----------------------------------------------------------------------------
50              
51             sub is_ppi_generic_statement {
52 953     953 1 1715 my $element = shift;
53              
54 953         2500 my $element_class = blessed($element);
55              
56 953 100       2178 return if not $element_class;
57 952 100       3246 return if not $element->isa('PPI::Statement');
58              
59 485         1542 return $element_class eq 'PPI::Statement';
60             }
61              
62             #-----------------------------------------------------------------------------
63              
64             sub is_ppi_statement_subclass {
65 384     384 1 868 my $element = shift;
66              
67 384         1086 my $element_class = blessed($element);
68              
69 384 100       875 return if not $element_class;
70 383 100       1077 return if not $element->isa('PPI::Statement');
71              
72 382         1358 return $element_class ne 'PPI::Statement';
73             }
74              
75             #-----------------------------------------------------------------------------
76              
77             # Can not use hashify() here because Perl::Critic::Utils already depends on
78             # this module.
79             Readonly::Hash my %SIMPLE_STATEMENT_CLASS => map { $_ => 1 } qw<
80             PPI::Statement
81             PPI::Statement::Break
82             PPI::Statement::Include
83             PPI::Statement::Null
84             PPI::Statement::Package
85             PPI::Statement::Variable
86             >;
87              
88             sub is_ppi_simple_statement {
89 1533 50   1533 1 5719 my $element = shift or return;
90              
91 1533 50       4771 my $element_class = blessed( $element ) or return;
92              
93 1533         6223 return $SIMPLE_STATEMENT_CLASS{ $element_class };
94             }
95              
96             #-----------------------------------------------------------------------------
97              
98             sub is_ppi_constant_element {
99 208 50   208 1 632 my $element = shift or return;
100              
101 208 50       851 blessed( $element ) or return;
102              
103             # TODO implement here documents once PPI::Token::HereDoc grows the
104             # necessary PPI::Token::Quote interface.
105             return
106 208   66     2774 $element->isa( 'PPI::Token::Number' )
107             || $element->isa( 'PPI::Token::Quote::Literal' )
108             || $element->isa( 'PPI::Token::Quote::Single' )
109             || $element->isa( 'PPI::Token::QuoteLike::Words' )
110             || (
111             $element->isa( 'PPI::Token::Quote::Double' )
112             || $element->isa( 'PPI::Token::Quote::Interpolate' ) )
113             && $element->string() !~ m< (?: \A | [^\\] ) (?: \\\\)* [\$\@] >smx
114             ;
115             }
116              
117             #-----------------------------------------------------------------------------
118              
119             sub is_subroutine_declaration {
120 1078     1078 1 8751 my $element = shift;
121              
122 1078 100       2741 return if not $element;
123              
124 1077 100       4291 return 1 if $element->isa('PPI::Statement::Sub');
125              
126 937 100       2240 if ( is_ppi_generic_statement($element) ) {
127 4         16 my $first_element = $element->first_element();
128              
129 4 100 66     45 return 1 if
      66        
130             $first_element
131             and $first_element->isa('PPI::Token::Word')
132             and $first_element->content() eq 'sub';
133             }
134              
135 934         3802 return;
136             }
137              
138             #-----------------------------------------------------------------------------
139              
140             sub is_in_subroutine {
141 288     288 1 9437 my ($element) = @_;
142              
143 288 100       1167 return if not $element;
144 286 50       824 return 1 if is_subroutine_declaration($element);
145              
146 286         895 while ( $element = $element->parent() ) {
147 786 100       4632 return 1 if is_subroutine_declaration($element);
148             }
149              
150 146         1128 return;
151             }
152              
153             #-----------------------------------------------------------------------------
154              
155             sub get_constant_name_element_from_declaring_statement {
156 0     0 1 0 my ($element) = @_;
157              
158 0         0 warnings::warnif(
159             'deprecated',
160             'Perl::Critic::Utils::PPI::get_constant_name_element_from_declaring_statement() is deprecated. Use PPIx::Utilities::Statement::get_constant_name_elements_from_declaring_statement() instead.',
161             );
162              
163 0 0       0 return if not $element;
164 0 0       0 return if not $element->isa('PPI::Statement');
165              
166 0 0 0     0 if ( $element->isa('PPI::Statement::Include') ) {
    0          
167 0         0 my $pragma;
168 0 0 0     0 if ( $pragma = $element->pragma() and $pragma eq 'constant' ) {
169 0         0 return _constant_name_from_constant_pragma($element);
170             }
171             }
172             elsif (
173             is_ppi_generic_statement($element)
174             and $element->schild(0)->content() =~ m< \A Readonly \b >xms
175             ) {
176 0         0 return $element->schild(2);
177             }
178              
179 0         0 return;
180             }
181              
182             sub _constant_name_from_constant_pragma {
183 0     0   0 my ($include) = @_;
184              
185 0 0       0 my @arguments = $include->arguments() or return;
186              
187 0         0 my $follower = $arguments[0];
188 0 0       0 return if not defined $follower;
189              
190 0         0 return $follower;
191             }
192              
193             #-----------------------------------------------------------------------------
194              
195             sub get_next_element_in_same_simple_statement {
196 525 50   525 1 1715 my $element = shift or return;
197              
198 525   66     2146 while ( $element and (
      66        
199             not is_ppi_simple_statement( $element )
200             or $element->parent()
201             and $element->parent()->isa( 'PPI::Structure::List' ) ) ) {
202 659         6182 my $next;
203 659 100       1953 $next = $element->snext_sibling() and return $next;
204 134         3028 $element = $element->parent();
205             }
206 0         0 return;
207              
208             }
209              
210             #-----------------------------------------------------------------------------
211              
212             sub get_previous_module_used_on_same_line {
213 195 50   195 1 887 my $element = shift or return;
214              
215 195 50       410 my ( $line ) = @{ $element->location() || []};
  195         721  
216              
217 195         3395 while (not is_ppi_simple_statement( $element )) {
218 239 50       2496 $element = $element->parent() or return;
219             }
220              
221 195         1952 while ( $element = $element->sprevious_sibling() ) {
222 189 50       30972 ( @{ $element->location() || []} )[0] == $line or return;
  189 100       725  
223 18 50       459 $element->isa( 'PPI::Statement::Include' )
224             and return $element->schild( 1 );
225             }
226              
227 6         204 return;
228             }
229              
230             #-----------------------------------------------------------------------------
231              
232             1;
233              
234             __END__
235              
236             =pod
237              
238             =for stopwords
239              
240             =head1 NAME
241              
242             Perl::Critic::Utils::PPI - Utility functions for dealing with PPI objects.
243              
244              
245             =head1 DESCRIPTION
246              
247             Provides classification of L<PPI::Elements|PPI::Elements>.
248              
249              
250             =head1 INTERFACE SUPPORT
251              
252             This is considered to be a public module. Any changes to its
253             interface will go through a deprecation cycle.
254              
255              
256             =head1 IMPORTABLE SUBS
257              
258             =over
259              
260             =item C<is_ppi_expression_or_generic_statement( $element )>
261              
262             Answers whether the parameter is an expression or an undifferentiated
263             statement. I.e. the parameter either is a
264             L<PPI::Statement::Expression|PPI::Statement::Expression> or the class
265             of the parameter is L<PPI::Statement|PPI::Statement> and not one of
266             its subclasses other than C<Expression>.
267              
268              
269             =item C<is_ppi_generic_statement( $element )>
270              
271             Answers whether the parameter is an undifferentiated statement, i.e.
272             the parameter is a L<PPI::Statement|PPI::Statement> but not one of its
273             subclasses.
274              
275              
276             =item C<is_ppi_statement_subclass( $element )>
277              
278             Answers whether the parameter is a specialized statement, i.e. the
279             parameter is a L<PPI::Statement|PPI::Statement> but the class of the
280             parameter is not L<PPI::Statement|PPI::Statement>.
281              
282              
283             =item C<is_ppi_simple_statement( $element )>
284              
285             Answers whether the parameter represents a simple statement, i.e. whether the
286             parameter is a L<PPI::Statement|PPI::Statement>,
287             L<PPI::Statement::Break|PPI::Statement::Break>,
288             L<PPI::Statement::Include|PPI::Statement::Include>,
289             L<PPI::Statement::Null|PPI::Statement::Null>,
290             L<PPI::Statement::Package|PPI::Statement::Package>, or
291             L<PPI::Statement::Variable|PPI::Statement::Variable>.
292              
293              
294             =item C<is_ppi_constant_element( $element )>
295              
296             Answers whether the parameter represents a constant value, i.e. whether the
297             parameter is a L<PPI::Token::Number|PPI::Token::Number>,
298             L<PPI::Token::Quote::Literal|PPI::Token::Quote::Literal>,
299             L<PPI::Token::Quote::Single|PPI::Token::Quote::Single>, or
300             L<PPI::Token::QuoteLike::Words|PPI::Token::QuoteLike::Words>, or is a
301             L<PPI::Token::Quote::Double|PPI::Token::Quote::Double> or
302             L<PPI::Token::Quote::Interpolate|PPI::Token::Quote::Interpolate> which does
303             not in fact contain any interpolated variables.
304              
305             This subroutine does B<not> interpret any form of here document as a constant
306             value, and may not until L<PPI::Token::HereDoc|PPI::Token::HereDoc> acquires
307             the relevant portions of the L<PPI::Token::Quote|PPI::Token::Quote> interface.
308              
309             This subroutine also does B<not> interpret entities created by the
310             L<Readonly|Readonly> module or the L<constant|constant> pragma as constants,
311             because the infrastructure to detect these appears not to be present, and the
312             author of this subroutine (B<not> Mr. Shank or Mr. Thalhammer) lacks the
313             knowledge/expertise/gumption to put it in place.
314              
315              
316             =item C<is_subroutine_declaration( $element )>
317              
318             Is the parameter a subroutine declaration, named or not?
319              
320              
321             =item C<is_in_subroutine( $element )>
322              
323             Is the parameter a subroutine or inside one?
324              
325              
326             =item C<get_constant_name_element_from_declaring_statement($statement)>
327              
328             B<This subroutine is deprecated.> You should use
329             L<PPIx::Utilities::Statement/get_constant_name_elements_from_declaring_statement()>
330             instead.
331              
332             Given a L<PPI::Statement|PPI::Statement>, if the statement is a C<use
333             constant> or L<Readonly|Readonly> declaration statement, return the name of
334             the thing being defined.
335              
336             Given
337              
338             use constant 1.16 FOO => 'bar';
339              
340             this will return "FOO". Similarly, given
341              
342             Readonly::Hash my %FOO => ( bar => 'baz' );
343              
344             this will return "%FOO".
345              
346             B<Caveat:> in the case where multiple constants are declared using the same
347             C<use constant> statement (e.g. C<< use constant { FOO => 1, BAR => 2 }; >>,
348             this subroutine will return the declaring
349             L<PPI::Structure::Constructor|PPI::Structure::Constructor>. In the case of
350             C<< use constant 1.16 { FOO => 1, BAR => 2 }; >> it may return a
351             L<PPI::Structure::Block|PPI::Structure::Block> instead of a
352             L<PPI::Structure::Constructor|PPI::Structure::Constructor>, due to a parse
353             error in L<PPI|PPI>.
354              
355              
356             =item C<get_next_element_in_same_simple_statement( $element )>
357              
358             Given a L<PPI::Element|PPI::Element>, this subroutine returns the next element
359             in the same simple statement as defined by is_ppi_simple_statement(). If no
360             next element can be found, this subroutine simply returns.
361              
362             If the $element is undefined or unblessed, we simply return.
363              
364             If the $element satisfies C<is_ppi_simple_statement()>, we return, B<unless>
365             it has a parent which is a L<PPI::Structure::List|PPI::Structure::List>.
366              
367             If the $element is the last significant element in its L<PPI::Node|PPI::Node>,
368             we replace it with its parent and iterate again.
369              
370             Otherwise, we return C<< $element->snext_sibling() >>.
371              
372              
373             =item C<get_previous_module_used_on_same_line( $element )>
374              
375             Given a L<PPI::Element|PPI::Element>, returns the L<PPI::Element|PPI::Element>
376             representing the name of the module included by the previous C<use> or
377             C<require> on the same line as the $element. If none is found, simply returns.
378              
379             For example, with the line
380              
381             use version; our $VERSION = ...;
382              
383             given the L<PPI::Token::Symbol|PPI::Token::Symbol> instance for C<$VERSION>, this will return
384             "version".
385              
386             If the given element is in a C<use> or <require>, the return is from the
387             previous C<use> or C<require> on the line, if any.
388              
389              
390             =back
391              
392              
393             =head1 AUTHOR
394              
395             Elliot Shank <perl@galumph.com>
396              
397              
398             =head1 COPYRIGHT
399              
400             Copyright (c) 2007-2011 Elliot Shank.
401              
402             This program is free software; you can redistribute it and/or modify
403             it under the same terms as Perl itself. The full text of this license
404             can be found in the LICENSE file included with this module.
405              
406             =cut
407              
408             # Local Variables:
409             # mode: cperl
410             # cperl-indent-level: 4
411             # fill-column: 78
412             # indent-tabs-mode: nil
413             # c-indentation-style: bsd
414             # End:
415             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :