File Coverage

blib/lib/Perl/Critic/Policy/Modules/ProhibitAutomaticExportation.pm
Criterion Covered Total %
statement 33 51 64.7
branch 3 18 16.6
condition 0 3 0.0
subroutine 14 20 70.0
pod 4 5 80.0
total 54 97 55.6


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::Modules::ProhibitAutomaticExportation;
2              
3 40     40   27110 use 5.010001;
  40         174  
4 40     40   253 use strict;
  40         110  
  40         835  
5 40     40   248 use warnings;
  40         120  
  40         1021  
6 40     40   245 use Readonly;
  40         124  
  40         2110  
7              
8 40     40   273 use Perl::Critic::Utils qw{ :severities };
  40         136  
  40         2091  
9 40     40   5357 use List::SomeUtils qw(any);
  40         94  
  40         2038  
10 40     40   296 use parent 'Perl::Critic::Policy';
  40         132  
  40         273  
11              
12             our $VERSION = '1.150';
13              
14             #-----------------------------------------------------------------------------
15              
16             Readonly::Scalar my $DESC => q{Symbols are exported by default};
17             Readonly::Scalar my $EXPL => q{Use '@EXPORT_OK' or '%EXPORT_TAGS' instead}; ## no critic (RequireInterpolation)
18              
19             #-----------------------------------------------------------------------------
20              
21 89     89 0 1640 sub supported_parameters { return () }
22 74     74 1 294 sub default_severity { return $SEVERITY_HIGH }
23 74     74 1 341 sub default_themes { return qw( core bugs ) }
24 32     32 1 93 sub applies_to { return 'PPI::Document' }
25              
26             #-----------------------------------------------------------------------------
27              
28             sub violates {
29 32     32 1 94 my ( $self, $elem, $doc ) = @_;
30              
31 32 50       139 if ( _uses_exporter($doc) ) {
32 0 0       0 if ( my $exp = _has_exports($doc) ) {
33 0         0 return $self->violation( $DESC, $EXPL, $exp );
34             }
35             }
36 32         701 return; #ok
37             }
38              
39             #-----------------------------------------------------------------------------
40              
41             sub _uses_exporter {
42 32     32   70 my ($doc) = @_;
43              
44 32         121 my $includes_ref = $doc->find('PPI::Statement::Include');
45 32 100       131 return if not $includes_ref;
46              
47             # This covers both C<use Exporter;> and C<use parent 'Exporter';>
48 30     61   154 return any { m/ \b Exporter \b/xms } @{ $includes_ref };
  61         751  
  30         177  
49             }
50              
51             #------------------
52              
53             sub _has_exports {
54 0     0     my ($doc) = @_;
55              
56             my $wanted =
57 0 0 0 0     sub { _our_export(@_) or _vars_export(@_) or _package_export(@_) };
  0            
58              
59 0           return $doc->find_first( $wanted );
60             }
61              
62             #------------------
63              
64             sub _our_export {
65 0     0     my (undef, $elem) = @_;
66              
67 0 0         $elem->isa('PPI::Statement::Variable') or return 0;
68 0 0         $elem->type() eq 'our' or return 0;
69              
70 0     0     return any { $_ eq '@EXPORT' } $elem->variables(); ## no critic(RequireInterpolationOfMetachars)
  0            
71             }
72              
73             #------------------
74              
75             sub _vars_export {
76 0     0     my (undef, $elem) = @_;
77              
78 0 0         $elem->isa('PPI::Statement::Include') or return 0;
79 0 0         $elem->pragma() eq 'vars' or return 0;
80              
81 0           return $elem =~ m{ \@EXPORT \b }xms; #Crude, but usually works
82             }
83              
84             #------------------
85              
86             sub _package_export {
87 0     0     my (undef, $elem) = @_;
88              
89 0 0         $elem->isa('PPI::Token::Symbol') or return 0;
90              
91 0           return $elem =~ m{ \A \@ \S+ ::EXPORT \z }xms;
92             #TODO: ensure that it is in _this_ package!
93             }
94              
95             1;
96              
97             __END__
98              
99             #-----------------------------------------------------------------------------
100              
101             =pod
102              
103             =head1 NAME
104              
105             Perl::Critic::Policy::Modules::ProhibitAutomaticExportation - Export symbols via C<@EXPORT_OK> or C<%EXPORT_TAGS> instead of C<@EXPORT>.
106              
107              
108             =head1 AFFILIATION
109              
110             This Policy is part of the core L<Perl::Critic|Perl::Critic>
111             distribution.
112              
113              
114             =head1 DESCRIPTION
115              
116             When using L<Exporter|Exporter>, symbols placed in the C<@EXPORT>
117             variable are automatically exported into the caller's namespace.
118             Although convenient, this practice is not polite, and may cause
119             serious problems if the caller declares the same symbols. The best
120             practice is to place your symbols in C<@EXPORT_OK> or C<%EXPORT_TAGS>
121             and let the caller choose exactly which symbols to export.
122              
123             package Foo;
124              
125             use Exporter 'import';
126             our @EXPORT = qw(foo $bar @baz); # not ok
127             our @EXPORT_OK = qw(foo $bar @baz); # ok
128             our %EXPORT_TAGS = ( all => [ qw(foo $bar @baz) ] ); # ok
129              
130              
131             =head1 CONFIGURATION
132              
133             This Policy is not configurable except for the standard options.
134              
135              
136             =head1 AUTHOR
137              
138             Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>
139              
140              
141             =head1 COPYRIGHT
142              
143             Copyright (c) 2005-2023 Imaginative Software Systems. All rights reserved.
144              
145             This program is free software; you can redistribute it and/or modify
146             it under the same terms as Perl itself. The full text of this license
147             can be found in the LICENSE file included with this module.
148              
149             =cut
150              
151             # Local Variables:
152             # mode: cperl
153             # cperl-indent-level: 4
154             # fill-column: 78
155             # indent-tabs-mode: nil
156             # c-indentation-style: bsd
157             # End:
158             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :