File Coverage

blib/lib/Perl/Critic/Policy/Subroutines/ProhibitCallsToUndeclaredSubs.pm
Criterion Covered Total %
statement 50 53 94.3
branch 11 12 91.6
condition n/a
subroutine 11 13 84.6
pod 5 6 83.3
total 77 84 91.6


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::Subroutines::ProhibitCallsToUndeclaredSubs;
2              
3 1     1   653 use strict;
  1         2  
  1         28  
4 1     1   4 use warnings;
  1         1  
  1         27  
5 1     1   3 use base 'Perl::Critic::Policy';
  1         1  
  1         90  
6              
7 1         98 use Perl::Critic::StricterSubs::Utils qw(
8             &find_declared_constant_names
9             &find_declared_subroutine_names
10             &find_imported_subroutine_names
11             &find_subroutine_calls
12             &get_package_names_from_include_statements
13 1     1   4 );
  1         1  
14              
15 1         40 use Perl::Critic::Utils qw(
16             :severities
17             &hashify
18             &is_qualified_name
19             &words_from_string
20 1     1   4 );
  1         1  
21              
22             #-----------------------------------------------------------------------------
23              
24             our $VERSION = 0.05;
25              
26             #-----------------------------------------------------------------------------
27              
28 0     0 0 0 sub supported_parameters { return qw(exempt_subs) }
29 19     19 1 131 sub default_severity { return $SEVERITY_HIGH }
30 0     0 1 0 sub default_themes { return qw( strictersubs bugs ) }
31 28     28 1 235883 sub applies_to { return 'PPI::Document' }
32              
33             #-----------------------------------------------------------------------------
34              
35             sub new {
36 28     28 1 101570 my ( $class, %args ) = @_;
37 28         183 my $self = bless {}, $class;
38 28         149 $self->{_exempt_subs} = {};
39              
40 28 100       119 if (defined $args{exempt_subs} ) {
41 5         20 for my $qualified_sub ( words_from_string( $args{exempt_subs} ) ){
42 10         39 my ($package, $sub_name) = _parse_sub_name( $qualified_sub );
43 10         37 $self->{_exempt_subs}->{$package}->{$sub_name} = 1;
44             }
45             }
46              
47 28         91 return $self;
48             }
49              
50             #-----------------------------------------------------------------------------
51              
52             sub _parse_sub_name {
53              
54 10     10   12 my $full_name = shift;
55              
56 10 50       49 if ( $full_name =~ m/\A ( .+ ) :: ([^:]+) \z/xms ) {
57              
58 10         29 my ($package_name, $sub_name) = ($1, $2);
59 10         28 return ($package_name, $sub_name);
60             }
61             else {
62              
63 0         0 die qq{Sub name "$full_name" must be fully qualifed.\n};
64             }
65             }
66              
67             #-----------------------------------------------------------------------------
68              
69             sub _is_exempt_subroutine {
70              
71 69     69   91 my ($self, $sub_name, $included_packages) = @_;
72 69         59 for my $package ( @{$included_packages} ) {
  69         95  
73 90 100       277 return 1 if exists $self->{_exempt_subs}->{$package}->{$sub_name};
74             }
75              
76 64         239 return;
77             }
78              
79             #-----------------------------------------------------------------------------
80              
81             sub violates {
82              
83 28     28 1 291 my ($self, undef, $doc) = @_;
84              
85 28         131 my @declared_constants = find_declared_constant_names( $doc );
86 28         95 my @declared_sub_names = find_declared_subroutine_names( $doc );
87 28         101 my @imported_sub_names = find_imported_subroutine_names( $doc );
88              
89 28         123 my %defined_sub_names = hashify(@declared_sub_names,
90             @imported_sub_names,
91             @declared_constants);
92              
93 28         272 my @included_packages = get_package_names_from_include_statements( $doc );
94              
95 28         405 my @violations = ();
96 28         100 for my $elem ( find_subroutine_calls($doc) ){
97              
98 78 100       2044 next if is_qualified_name( $elem );
99 69 100       666 next if $self->_is_exempt_subroutine( $elem, \@included_packages );
100              
101 64         112 my ( $name ) = ( $elem =~ m{&?(\w+)}mxs );
102 64 100       432 if ( not exists $defined_sub_names{$name} ){
103 19         23 my $expl = q{This might be a major bug};
104 19         38 my $desc = qq{Subroutine "$elem" is neither declared nor explicitly imported};
105 19         93 push @violations, $self->violation($desc, $expl, $elem);
106             }
107             }
108              
109 28         928 return @violations;
110             }
111              
112             #-----------------------------------------------------------------------------
113              
114             1;
115              
116             __END__
117              
118             =pod
119              
120             =head1 NAME
121              
122             Perl::Critic::Policy::Subroutines::ProhibitCallsToUndeclaredSubs
123              
124             =head1 AFFILIATION
125              
126             This policy is part of L<Perl::Critic::StricterSubs|Perl::Critic::StricterSubs>.
127              
128             =head1 DESCRIPTION
129              
130             This Policy checks that every unqualified subroutine call has a matching
131             subroutine declaration in the current file, or that it explicitly appears in
132             the import list for one of the included modules.
133              
134             Some modules do not use the L<Exporter|Exporter> interface, and rely on other
135             mechanisms to export symbols into your code. In those cases, this Policy will
136             report a false violation. However, you can instruct this policy to ignore a
137             particular subroutine name, as long as the appropriate package has been
138             included in your file. See L</"CONFIGURATION"> for more details.
139              
140             =head1 CONFIGURATION
141              
142             A list of exempt subroutines for this Policy can defined by specifying
143             'exempt_subs' as a string of space-delimited, fully-qualified subroutine
144             names. For example, putting this in your F<.perlcriticrc> file would allow
145             you to call the C<ok> and C<is> functions without explicitly importing or
146             declaring those functions, as long as the C<Test::More> package has been
147             included in the file somewhere.
148              
149             [Subroutines::ProhibitCallsToUndeclaredSubs]
150             exempt_subs = Test::More::ok Test::More::is
151              
152             By default, there are no exempt subroutines, but we're working on compiling a
153             list of the most common ones.
154              
155             =head1 LIMITATIONS
156              
157             This Policy assumes that the file has no more than one C<package> declaration
158             and that all subs declared within the file are, in fact, declared into that
159             same package. In most cases, violating either of these assumptions means
160             you're probably doing something that you shouldn't do. Think twice about what
161             you're doing.
162              
163             Also, if you C<require> a module and subsequently call the C<import> method on
164             that module, this Policy will not detect the symbols that might have been
165             imported. In which case, you'll probably get bogus violations.
166              
167              
168             =head1 AUTHOR
169              
170             Jeffrey Ryan Thalhammer <thaljef@cpan.org>
171              
172             =head1 COPYRIGHT
173              
174             Copyright (c) 2007 Jeffrey Ryan Thalhammer. All rights reserved.
175              
176             This program is free software; you can redistribute it and/or modify it under
177             the same terms as Perl itself. The full text of this license can be found in
178             the LICENSE file included with this module.
179              
180             =cut
181              
182             ##############################################################################
183             # Local Variables:
184             # mode: cperl
185             # cperl-indent-level: 4
186             # fill-column: 78
187             # indent-tabs-mode: nil
188             # c-indentation-style: bsd
189             # End:
190             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab :