File Coverage

blib/lib/Perl/Critic/Policy/Modules/ProhibitAutomaticExportation.pm
Criterion Covered Total %
statement 51 51 100.0
branch 17 18 94.4
condition 3 3 100.0
subroutine 19 19 100.0
pod 4 5 80.0
total 94 96 97.9


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::Modules::ProhibitAutomaticExportation;
2              
3 40     40   27731 use 5.010001;
  40         185  
4 40     40   264 use strict;
  40         116  
  40         875  
5 40     40   220 use warnings;
  40         98  
  40         968  
6 40     40   229 use Readonly;
  40         120  
  40         2162  
7              
8 40     40   327 use Perl::Critic::Utils qw{ :severities };
  40         119  
  40         2238  
9 40     40   5443 use List::SomeUtils qw(any);
  40         149  
  40         2201  
10 40     40   317 use parent 'Perl::Critic::Policy';
  40         155  
  40         284  
11              
12             our $VERSION = '1.146';
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 98     98 0 1693 sub supported_parameters { return () }
22 77     77 1 352 sub default_severity { return $SEVERITY_HIGH }
23 74     74 1 354 sub default_themes { return qw( core bugs ) }
24 41     41 1 150 sub applies_to { return 'PPI::Document' }
25              
26             #-----------------------------------------------------------------------------
27              
28             sub violates {
29 41     41 1 125 my ( $self, $elem, $doc ) = @_;
30              
31 41 100       185 if ( _uses_exporter($doc) ) {
32 8 100       227 if ( my $exp = _has_exports($doc) ) {
33 3         115 return $self->violation( $DESC, $EXPL, $exp );
34             }
35             }
36 38         793 return; #ok
37             }
38              
39             #-----------------------------------------------------------------------------
40              
41             sub _uses_exporter {
42 41     41   109 my ($doc) = @_;
43              
44 41         161 my $includes_ref = $doc->find('PPI::Statement::Include');
45 41 100       171 return if not $includes_ref;
46              
47             # This covers both C<use Exporter;> and C<use parent 'Exporter';>
48 38         107 return scalar grep { m/ \b Exporter \b/xms } @{ $includes_ref };
  73         1009  
  38         98  
49             }
50              
51             #------------------
52              
53             sub _has_exports {
54 8     8   17 my ($doc) = @_;
55              
56             my $wanted =
57 8 100 100 171   51 sub { _our_export(@_) or _vars_export(@_) or _package_export(@_) };
  171         1835  
58              
59 8         30 return $doc->find_first( $wanted );
60             }
61              
62             #------------------
63              
64             sub _our_export {
65 171     171   295 my (undef, $elem) = @_;
66              
67 171 100       677 $elem->isa('PPI::Statement::Variable') or return 0;
68 2 50       11 $elem->type() eq 'our' or return 0;
69              
70 2     2   104 return any { $_ eq '@EXPORT' } $elem->variables(); ## no critic(RequireInterpolationOfMetachars)
  2         115  
71             }
72              
73             #------------------
74              
75             sub _vars_export {
76 170     170   307 my (undef, $elem) = @_;
77              
78 170 100       678 $elem->isa('PPI::Statement::Include') or return 0;
79 12 100       38 $elem->pragma() eq 'vars' or return 0;
80              
81 4         127 return $elem =~ m{ \@EXPORT \b }xms; #Crude, but usually works
82             }
83              
84             #------------------
85              
86             sub _package_export {
87 169     169   716 my (undef, $elem) = @_;
88              
89 169 100       690 $elem->isa('PPI::Token::Symbol') or return 0;
90              
91 6         18 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-2021 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 :