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   122724 use 5.010001;
  40         169  
4 40     40   217 use strict;
  40         117  
  40         821  
5 40     40   201 use warnings;
  40         96  
  40         906  
6              
7 40     40   746 use Readonly;
  40         4145  
  40         1868  
8              
9 40     40   243 use Scalar::Util qw< blessed >;
  40         94  
  40         1780  
10              
11 40     40   244 use Exporter 'import';
  40         109  
  40         46665  
12              
13             our $VERSION = '1.148';
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 3365 my $element = shift;
38              
39 638 100       2812 return if not $element;
40 637 100       1985 return if not $element->isa('PPI::Statement');
41 636 100       2408 return 1 if $element->isa('PPI::Statement::Expression');
42              
43 254         717 my $element_class = blessed($element);
44              
45 254 50       605 return if not $element_class;
46 254         1027 return $element_class eq 'PPI::Statement';
47             }
48              
49             #-----------------------------------------------------------------------------
50              
51             sub is_ppi_generic_statement {
52 953     953 1 2139 my $element = shift;
53              
54 953         2530 my $element_class = blessed($element);
55              
56 953 100       2276 return if not $element_class;
57 952 100       3333 return if not $element->isa('PPI::Statement');
58              
59 485         1631 return $element_class eq 'PPI::Statement';
60             }
61              
62             #-----------------------------------------------------------------------------
63              
64             sub is_ppi_statement_subclass {
65 384     384 1 965 my $element = shift;
66              
67 384         1056 my $element_class = blessed($element);
68              
69 384 100       873 return if not $element_class;
70 383 100       1076 return if not $element->isa('PPI::Statement');
71              
72 382         1525 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 5710 my $element = shift or return;
90              
91 1533 50       4671 my $element_class = blessed( $element ) or return;
92              
93 1533         6068 return $SIMPLE_STATEMENT_CLASS{ $element_class };
94             }
95              
96             #-----------------------------------------------------------------------------
97              
98             sub is_ppi_constant_element {
99 208 50   208 1 660 my $element = shift or return;
100              
101 208 50       891 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     2593 $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 8540 my $element = shift;
121              
122 1078 100       2713 return if not $element;
123              
124 1077 100       4218 return 1 if $element->isa('PPI::Statement::Sub');
125              
126 937 100       2169 if ( is_ppi_generic_statement($element) ) {
127 4         15 my $first_element = $element->first_element();
128              
129 4 100 66     43 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         3906 return;
136             }
137              
138             #-----------------------------------------------------------------------------
139              
140             sub is_in_subroutine {
141 288     288 1 9248 my ($element) = @_;
142              
143 288 100       1113 return if not $element;
144 286 50       915 return 1 if is_subroutine_declaration($element);
145              
146 286         912 while ( $element = $element->parent() ) {
147 786 100       4359 return 1 if is_subroutine_declaration($element);
148             }
149              
150 146         1288 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 1706 my $element = shift or return;
197              
198 525   66     1994 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         5514 my $next;
203 659 100       1825 $next = $element->snext_sibling() and return $next;
204 134         2849 $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 789 my $element = shift or return;
214              
215 195 50       338 my ( $line ) = @{ $element->location() || []};
  195         606  
216              
217 195         3054 while (not is_ppi_simple_statement( $element )) {
218 239 50       2243 $element = $element->parent() or return;
219             }
220              
221 195         1729 while ( $element = $element->sprevious_sibling() ) {
222 189 50       28563 ( @{ $element->location() || []} )[0] == $line or return;
  189 100       498  
223 18 50       453 $element->isa( 'PPI::Statement::Include' )
224             and return $element->schild( 1 );
225             }
226              
227 6         193 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 :