File Coverage

blib/lib/Perl/Critic/StricterSubs/Utils.pm
Criterion Covered Total %
statement 184 195 94.3
branch 81 100 81.0
condition 23 36 63.8
subroutine 29 30 96.6
pod 11 11 100.0
total 328 372 88.1


line stmt bran cond sub pod time code
1              
2             use strict;
3 1     1   6 use warnings;
  1         2  
  1         25  
4 1     1   4  
  1         9  
  1         24  
5             use base 'Exporter';
6 1     1   5  
  1         2  
  1         80  
7             use Carp qw(croak);
8 1     1   6  
  1         1  
  1         52  
9             use List::MoreUtils qw( any );
10 1     1   6 use Perl::Critic::Utils qw(
  1         11  
  1         9  
11 1         41 :characters
12             :severities
13             &first_arg
14             &hashify
15             &is_function_call
16             &is_perl_builtin
17             &words_from_string
18             );
19 1     1   599  
  1         2  
20             #-----------------------------------------------------------------------------
21              
22             our $VERSION = 0.06;
23              
24             #-----------------------------------------------------------------------------
25              
26             our @EXPORT_OK = qw{
27             &find_exported_subroutine_names
28             &find_declared_subroutine_names
29             &find_declared_constant_names
30             &find_imported_subroutine_names
31             &find_subroutine_calls
32             &get_all_subs_from_list_of_symbols
33             &get_package_names_from_include_statements
34             &get_package_names_from_package_statements
35             &parse_literal_list
36             &parse_quote_words
37             &parse_simple_list
38             };
39              
40             #-----------------------------------------------------------------------------
41              
42             my ($list_node) = @_;
43              
44 12     12 1 53 # Per RT 36783, lists may contain qw{...} strings as well as words. We
45             # don't need to look for nested lists because they are of interest only
46             # for their contents, which we get by looking for them directly.
47             my @strings = map { $_->string() }
48             @{ $list_node->find( 'PPI::Token::Quote' ) || [] };
49 20         2862 push @strings, map { parse_quote_words( $_ ) }
50 12 100       15 @{ $list_node->find( 'PPI::Token::QuoteLike::Words' ) || [] };
  12         29  
51 1         187  
52 12 100       410 return @strings; #Just hoping that these are single words
  12         26  
53             }
54 12         2853  
55             #-----------------------------------------------------------------------------
56              
57             my (@nodes) = @_;
58             my @string_elems = grep { $_->isa('PPI::Token::Quote') } @nodes;
59             return if not @string_elems;
60 0     0 1 0  
61 0         0 my @strings = map { $_->string() } @string_elems;
  0         0  
62 0 0       0 return @strings; #Just hoping that these are single words
63             }
64 0         0  
  0         0  
65 0         0 #-----------------------------------------------------------------------------
66              
67             my ($qw_elem) = @_;
68             my ($word_string) = ( $qw_elem =~ m{\A qw \s* . (.*) .\z}msx );
69             my @words = words_from_string( $word_string || $EMPTY );
70             return @words;
71 16     16 1 28 }
72 16         60  
73 16   33     135 #-----------------------------------------------------------------------------
74 16         116  
75             my $doc = shift;
76              
77             my $statements = $doc->find( \&_wanted_include_statement );
78             return () if not $statements;
79              
80 52     52 1 81 return map { $_->module() } @{$statements};
81             }
82 52         119  
83 52 100       526 #-----------------------------------------------------------------------------
84              
85 30         44 my $doc = shift;
  54         497  
  30         66  
86              
87             my $statements = $doc->find( 'PPI::Statement::Package' );
88             return () if not $statements;
89              
90             return map { $_->namespace() } @{$statements};
91 24     24 1 37 }
92              
93 24         61 #-----------------------------------------------------------------------------
94 24 100       301  
95             my ($doc, $element) = @_;
96 4         8  
  4         19  
  4         6  
97             return 0 if not $element->isa('PPI::Statement::Include');
98              
99             # This will block out file names, e.g. require 'Foo.pm';
100             return 0 if not $element->module();
101              
102 2706     2706   23145 # Skip 'no' as in 'no strict'
103             my $include_type = $element->type();
104 2706 100       6703 return 0 if $include_type ne 'use' && $include_type ne 'require';
105              
106             return 1;
107 59 100       122 }
108              
109             #-----------------------------------------------------------------------------
110 54         1114  
111 54 50 66     848 my ($doc, @export_types) = @_;
112              
113 54         94 @export_types = @export_types ?
114             @export_types : qw{@EXPORT @EXPORT_OK};
115              
116             my @all_exports = ();
117             for my $export_type( @export_types ) {
118              
119 10     10   16 my $export_assignment = _find_export_assignment( $doc, $export_type );
120             next if not $export_assignment;
121 10 50       27  
122             my @exports = _parse_export_list( $export_assignment );
123             foreach (@exports) { s/ \A & //xms; } # Strip all sub sigils
124 10         13 push @all_exports, @exports;
125 10         18 }
126              
127 20         35 return @all_exports;
128 20 100       47 }
129              
130 12         66 #-----------------------------------------------------------------------------
131 12         23  
  41         71  
132 12         30 my ($doc, @export_types) = @_;
133              
134             my @exports = _find_exported_names( $doc, @export_types );
135 10         27 return get_all_subs_from_list_of_symbols( @exports );
136             }
137              
138             #-----------------------------------------------------------------------------
139              
140             my ($doc) = @_;
141 10     10 1 16 my $sub_nodes = $doc->find('PPI::Statement::Sub');
142             return if not $sub_nodes;
143 10         20  
144 10         24 my @sub_names = map { $_->name() } @{ $sub_nodes };
145             for (@sub_names) { s{\A .*::}{}mxs }; # Remove leading package name
146             return @sub_names;
147             }
148              
149             #-----------------------------------------------------------------------------
150 34     34 1 50  
151 34         74 my ($doc) = @_;
152 34 100       362  
153             my $includes_ref = $doc->find('PPI::Statement::Include');
154 7         12 return if not $includes_ref;
  9         128  
  7         20  
155 7         305  
  9         22  
156 7         37 my @use_stmnts = grep { $_->type() eq 'use' } @{ $includes_ref };
157              
158             my @imported_symbols =
159             map { _get_imports_from_use_statements($_) } @use_stmnts;
160              
161             my @imported_sub_names =
162 28     28 1 42 get_all_subs_from_list_of_symbols( @imported_symbols );
163              
164 28         55 return @imported_sub_names;
165 28 100       225 }
166              
167 16         23 #-----------------------------------------------------------------------------
  31         282  
  16         30  
168              
169             my ($use_stmnt) = @_;
170 16         262  
  28         48  
171             # In a typical C<use> statement, the first child is "use", and the
172 16         34 # second child is the package name (a bareword). Everything after
173             # that (except the trailing semi-colon) is part of the import
174             # arguments.
175 16         44  
176             my @schildren = $use_stmnt->schildren();
177             my @import_args = @schildren[2 .. $#schildren - 1];
178              
179             my $first_import_arg = $import_args[0];
180             return if not defined $first_import_arg;
181 28     28   45  
182             # RT 43310 is a pathological case, which shows we can't simply look at the
183             # first token after the module name to tell what to do. So we iterate over
184             # the entire argument list, scavenging what we recognize, and hoping the
185             # rest is structure (commas and such).
186             my @result;
187             foreach my $import_rqst ( @import_args ) {
188 28         53  
189 28         341 defined $import_rqst
190             or next;
191 28         38  
192 28 100       56 if ( $import_rqst->isa( 'PPI::Token::QuoteLike::Words' ) ) {
193              
194             push @result, parse_quote_words( $import_rqst );
195              
196             } elsif ( $import_rqst->isa( 'PPI::Structure::List' ) ) {
197              
198 22         30 push @result, parse_simple_list ( $import_rqst );
199 22         42  
200             } elsif ( $import_rqst->isa( 'PPI::Token::Quote' ) ) {
201 37 50       86  
202             push @result, $import_rqst->string();
203              
204 37 100       131 }
    100          
    100          
205              
206 8         23 }
207              
208             return @result;
209              
210 7         107 }
211              
212             #-----------------------------------------------------------------------------
213              
214 11         33 my ($doc) = @_;
215              
216             my $constant_pragmas_ref = $doc->find( \&_is_constant_pragma );
217             return if not $constant_pragmas_ref;
218             my @declared_constants = ();
219              
220 22         79 for my $constant_pragma ( @{$constant_pragmas_ref} ) {
221              
222             #######################################################
223             # Constant pragmas typically look like one of these:
224             # use constant (AVAGADRO => 6.02*10^23); # With parens
225             # use constant PI => 3.1415927; # Without parens
226             # use constant {FOO => 1, BAR => 1} # Block form
227 34     34 1 49 #######################################################
228              
229 34         82 my $pragma_bareword = $constant_pragma->schild(1);
230 34 100       370 my $sibling = $pragma_bareword->snext_sibling();
231 3         7  
232             if ( defined $sibling && $sibling->isa('PPI::Structure::Constructor') ) {
233 3         5 # Parse the multi-constant block form...
  3         8  
234             push @declared_constants, _get_keys_of_hash($sibling);
235             }
236             else {
237             # Parse the single-constant declaration
238             my $constant_name = first_arg( $pragma_bareword ) || next;
239             push @declared_constants, $constant_name->content();
240             }
241              
242 7         23 }
243 7         90 return @declared_constants;
244             }
245 7 100 66     152  
246             #-----------------------------------------------------------------------------
247 2         8  
248             my ($block_or_list_node) = @_;
249             return if not defined $block_or_list_node;
250              
251 5   50     77 my $fat_commas = $block_or_list_node->find( \&_is_fat_comma )
252 5         273 or return;
253              
254             my @keys = map { $_->sprevious_sibling() } @{$fat_commas};
255             return @keys;
256 3         17 }
257              
258             #-----------------------------------------------------------------------------
259              
260             my( undef, $elem) = @_;
261             return $elem->isa('PPI::Token::Operator')
262 2     2   5 && $elem eq $FATCOMMA;
263 2 50       7 }
264              
265 2 50       9 #-----------------------------------------------------------------------------
266              
267             my (undef, $elem) = @_;
268 2         26  
  5         77  
  2         6  
269 2         58 return $elem->isa('PPI::Statement::Include')
270             && $elem->pragma() eq 'constant'
271             && $elem->type() eq 'use';
272             }
273              
274             #-----------------------------------------------------------------------------
275 39     39   371  
276 39   100     115 my ($doc) = @_;
277              
278             my $sub_calls_ref = $doc->find( \&_is_subroutine_call );
279             return if not $sub_calls_ref;
280             return @{$sub_calls_ref};
281             }
282              
283 1994     1994   18124 #-----------------------------------------------------------------------------
284              
285 1994   66     5627 my ($doc, $elem) = @_;
286              
287             if ( $elem->isa('PPI::Token::Word') ) {
288              
289             return 0 if is_perl_builtin( $elem );
290             return 0 if _smells_like_filehandle( $elem );
291             return 0 if _smells_like_label( $elem );
292             return 1 if is_function_call( $elem );
293 33     33 1 51  
294             }
295 33         76 elsif ($elem->isa('PPI::Token::Symbol')) {
296 33 100       332  
297 28         37 return 1 if $elem->symbol_type eq q{&};
  28         91  
298             }
299              
300             return 0;
301             }
302              
303 2106     2106   37781 #-----------------------------------------------------------------------------
304              
305 2106 100       6093 my %functions_that_take_filehandles =
    100          
306             hashify( qw(print printf read write sysopen tell open close) );
307 243 100       426  
308 164 100       2874 my ($elem) = @_;
309 147 100       643 return if not $elem;
310 142 100       480  
311             #--------------------------------------------------------------------
312             # This handles calls *without* parens, for example:
313             # open HANDLE, $path;
314             # print HANDLE 'Hello World';
315 85 100       188 # close HANDLE;
316              
317             if ( my $left_sib = $elem->sprevious_sibling ){
318 1898         12027 return exists $functions_that_take_filehandles{ $left_sib }
319             && is_function_call( $left_sib );
320             }
321              
322             #--------------------------------------------------------------------
323             # This handles calls *with* parens, for example:
324             # open( HANDLE, $path );
325             # print( HANDLE 'Hello World' );
326             # close( HANDLE );
327 164     164   235 #
328 164 50       331 # Or this case (Conway-style):
329             # print {HANDLE} 'Hello World';
330              
331             my $expression = $elem->parent() || return;
332             my $enclosing_node = $expression->parent() || return;
333              
334             return if ! ( $enclosing_node->isa('PPI::Structure::List')
335             || $enclosing_node->isa('PPI::Structure::Block') );
336 164 100       327  
337 72   66     1546 return if $enclosing_node->schild(0) != $expression;
338              
339             if ( my $left_uncle = $enclosing_node->sprevious_sibling ){
340             return exists $functions_that_take_filehandles{ $left_uncle }
341             && is_function_call( $left_uncle );
342             }
343              
344             return;
345             }
346              
347             #-----------------------------------------------------------------------------
348              
349             my %functions_that_take_labels =
350 92   50     1442 hashify( qw( last next redo ) );
351 92   50     415  
352             # The following is cribbed shamelessly from _looks_like_filehandle. TRW
353 92 100 100     747  
354             my ($elem) = @_;
355             return if not $elem;
356 18 100       86  
357             #--------------------------------------------------------------------
358 17 50       278 # This handles calls *without* parens, for example:
359 17   66     330 # next FOO
360             # last BAR
361             # redo BAZ
362              
363 0         0 if ( my $left_sib = $elem->sprevious_sibling ){
364             return exists $functions_that_take_labels{ $left_sib };
365             }
366              
367             #--------------------------------------------------------------------
368             # This handles calls *with* parens, for example:
369             # next ( FOO )
370             # last ( BAR )
371             # redo ( BAZ )
372             #
373             # The above actually work, at least under 5.6.2 and 5.14.2.
374 147     147   208 # next { FOO }
375 147 50       304 # does _not_ work under those Perls, so we don't check for it.
376              
377             my $expression = $elem->parent() || return;
378             my $enclosing_node = $expression->parent() || return;
379              
380             return if ! ( $enclosing_node->isa('PPI::Structure::List') );
381              
382             return if $enclosing_node->schild(0) != $expression;
383 147 100       251  
384 63         1144 if ( my $left_uncle = $enclosing_node->sprevious_sibling ){
385             return exists $functions_that_take_labels{ $left_uncle };
386             }
387              
388             return;
389             }
390              
391             #-----------------------------------------------------------------------------
392              
393             my @symbols = @_;
394              
395             my @sub_names = grep { m/\A [&\w]/mxs } @symbols;
396             for (@sub_names) { s/\A &//mxs; } # Remove optional sigil
397 84   50     1172  
398 84   50     372 return @sub_names
399             }
400 84 100       470  
401             #-----------------------------------------------------------------------------
402 6 50       38  
403             my ($doc, $export_type) = @_;
404 6 50       92  
405 6         121 my $wanted = _make_assignment_finder( $export_type );
406             my $export_assignments = $doc->find( $wanted );
407             return if not $export_assignments;
408 0         0  
409             croak qq{Found multiple $export_type lists\n}
410             if @{$export_assignments} > 1;
411              
412             return $export_assignments->[0];
413             }
414 26     26 1 48  
415             #-----------------------------------------------------------------------------
416 26         42  
  73         160  
417 26         44 my ($wanted_symbol) = @_;
  50         78  
418              
419             #############################################################
420 26         70 # This function returns a callback functiaon that is suitable
421             # for use with the PPI::Node::find() method. It will find
422             # all the occurances of the $wanted_symbol where the symbol
423             # is on the immediate left-hand side of the assignment operator.
424             ##############################################################
425 20     20   34  
426             my $finder = sub {
427 20         32  
428 20         48 my ($doc, $elem) = @_;
429 20 100       230  
430             return 0 if not $elem->isa('PPI::Token::Symbol');
431             return 0 if $elem ne $wanted_symbol;
432 12 50       16  
  12         25  
433             # Check if symbol is on left-hand side of assignment
434 12         52 my $next_sib = $elem->snext_sibling() || return 0;
435             return 0 if not $next_sib->isa('PPI::Token::Operator');
436             return 0 if $next_sib ne q{=};
437              
438             return 1;
439             };
440 20     20   28  
441             return $finder;
442             }
443              
444             #-----------------------------------------------------------------------------
445              
446             my ($export_symbol) = @_;
447              
448             # First element after the symbol should be "="
449             my $snext_sibling = $export_symbol->snext_sibling();
450             return if not $snext_sibling;
451 1062     1062   8263  
452              
453 1062 100       2580 # Gather up remaining elements
454 26 100       59 my @left_hand_side = ();
455             while ( $snext_sibling = $snext_sibling->snext_sibling() ) {
456             push @left_hand_side, $snext_sibling;
457 13   50     189 }
458 13 100       292  
459 12 50       25 # Did we get any?
460             return if not @left_hand_side;
461 12         172  
462 20         65  
463             #Now parse the rest based on type of first element
464 20         35 my $first_element = $left_hand_side[0];
465             return parse_quote_words( $first_element )
466             if $first_element->isa('PPI::Token::QuoteLike::Words');
467              
468             return parse_simple_list( $first_element )
469             if $first_element->isa('PPI::Structure::List');
470 12     12   22  
471             return parse_literal_list( @left_hand_side )
472             if $first_element->isa('PPI::Token::Quote');
473 12         25  
474 12 50       254  
475             return; #Don't know what do do!
476             }
477              
478 12         17 #-----------------------------------------------------------------------------
479 12         29  
480 24         458 1;
481              
482              
483             =pod
484 12 50       256  
485             =for stopwords INIT typeglob distro
486              
487             =head1 NAME
488 12         18  
489 12 100       35 Perl::Critic::StricterSubs::Utils
490              
491             =head1 AFFILIATION
492 5 50       40  
493             This module is part of L<Perl::Critic::StricterSubs|Perl::Critic::StricterSubs>.
494              
495 0 0         =head1 DESCRIPTION
496              
497             This module holds utility methods that are shared by other modules in the
498             L<Perl::Critic::StricterSubs|Perl::Critic::StricterSubs> distro. Until this distro becomes more mature,
499 0           I would discourage you from using these subs outside of this distro.
500              
501             =head1 IMPORTABLE SUBS
502              
503             =over
504              
505             =item C<parse_quote_words( $qw_elem )>
506              
507             Gets the words from a L<PPI::Token::Quotelike::Words|PPI::Token::Quotelike::Words>.
508              
509             =item C<parse_simple_list( $list_node )>
510              
511             Returns the string literals from a L<PPI::Structure::List|PPI::Structure::List>.
512              
513             =item C<parse_literal_list( @nodes )>
514              
515             Returns the string literals contained anywhere in a collection of
516             L<PPI::Node|PPI::Node>s.
517              
518             =item C<find_declared_subroutine_names( $doc )>
519              
520             Returns a list of the names for all the subroutines that are declared in the
521             document. The package will be stripped from the name. TODO: Give examples of
522             what this will return for a given $doc.
523              
524             =item C<find_declared_constant_names( $doc )>
525              
526             Returns a list of the names for all the constants that were declared in the
527             document using the C<constant> pragma. At the moment, only these styles of
528             declaration is supported:
529              
530             use constant 'FOO' => 42; #with quotes, no parens
531             use constant BAR => 27; #no quotes, no parens
532             use constant (BAZ => 98); #no quotes, with parens
533              
534             Multiple declarations per pragma are not supported at all:
535              
536             use constant {WANGO => 1, TANGO => 2}; #no love here.
537              
538             =item C<find_imported_subroutine_names( $doc )>
539              
540             Returns a list of the names of all subroutines that are imported into the
541             document via C<use MODULE LIST;>. The leading ampersand sigil will be
542             stripped. TODO: Give examples of what this will return for a given $doc.
543              
544             =item C<find_subroutine_calls( $doc )>
545              
546             Returns a list C<PPI::Element>s, where each is the bareword name of a static
547             subroutine invocation. If the subroutine call is fully-qualified the package
548             will still be attached to the name. In all cases, the leading sigil will be
549             removed. TODO: Give examples of what this will return for a given $doc.
550              
551             =item C<find_exported_subroutine_names( $doc )>
552              
553             Returns a list of the names of each subroutine that is marked for exportation
554             via C<@EXPORT> or C<@EXPORT_OK>. Be aware that C<%EXPORT_TAGS> are not
555             supported here. TODO: Give examples of what this will return for a given
556             $doc.
557              
558             =item C<get_package_names_from_include_statements( $doc )>
559              
560             Returns a list of module names referred to with a bareword in an
561             include statement. This covers all include statements, such as:
562              
563             use Foo;
564             require Foo;
565              
566             sub load_foo {
567             require Foo if $condition;
568             }
569              
570             eval{ require Foo };
571              
572             INIT {
573             require Foo;
574             }
575              
576             But it does not cover these:
577              
578             require "Foo.pm";
579             eval { require $foo };
580              
581             =item C<get_package_names_from_package_statements( $doc )>
582              
583             Returns a list of all the namespaces from all the packages statements
584             that appear in the document.
585              
586             =item C<find_exported_sub_names( $doc, @export_types )>
587              
588             Returns a list of subroutines which are exported via the specified export
589             types. If C<@export_types> is empty, it defaults to C<qw{ @EXPORT, @EXPORT_OK
590             }>.
591              
592             Subroutine names are returned as in
593             C<get_all_subs_from_list_of_symbols()>.
594              
595             =item C<get_all_subs_from_list_of_symbols( @symbols )>
596              
597             Returns a list of all the input symbols which could be subroutine
598             names.
599              
600             Subroutine names are considered to be those symbols that don't have
601             scalar, array, hash, or glob sigils. Any subroutine sigils are
602             stripped off; i.e. C<&foo> will be returned as "foo".
603              
604             =back
605              
606             =head1 SEE ALSO
607              
608             L<Exporter|Exporter>
609              
610             =head1 AUTHOR
611              
612             Jeffrey Ryan Thalhammer <thaljef@cpan.org>
613              
614             =head1 COPYRIGHT
615              
616             Copyright (c) 2007 Jeffrey Ryan Thalhammer. All rights reserved.
617              
618             This program is free software; you can redistribute it and/or modify
619             it under the same terms as Perl itself. The full text of this license
620             can be found in the LICENSE file included with this module.
621              
622             =cut
623              
624              
625             ##############################################################################
626             # Local Variables:
627             # mode: cperl
628             # cperl-indent-level: 4
629             # fill-column: 78
630             # indent-tabs-mode: nil
631             # c-indentation-style: bsd
632             # End:
633             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab :