File Coverage

blib/lib/Perl/Critic/Policy/Modules/ProhibitUseQuotedVersion.pm
Criterion Covered Total %
statement 43 43 100.0
branch 7 8 87.5
condition 3 5 60.0
subroutine 13 13 100.0
pod 1 2 50.0
total 67 71 94.3


line stmt bran cond sub pod time code
1             # Copyright 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019, 2021 Kevin Ryde
2              
3             # Perl-Critic-Pulp is free software; you can redistribute it and/or modify
4             # it under the terms of the GNU General Public License as published by the
5             # Free Software Foundation; either version 3, or (at your option) any later
6             # version.
7             #
8             # Perl-Critic-Pulp is distributed in the hope that it will be useful, but
9             # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10             # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11             # for more details.
12             #
13             # You should have received a copy of the GNU General Public License along
14             # with Perl-Critic-Pulp. If not, see <http://www.gnu.org/licenses/>.
15              
16              
17             package Perl::Critic::Policy::Modules::ProhibitUseQuotedVersion;
18 40     40   31177 use 5.006;
  40         154  
19 40     40   217 use strict;
  40         87  
  40         867  
20 40     40   192 use warnings;
  40         90  
  40         1243  
21 40     40   238 use base 'Perl::Critic::Policy';
  40         91  
  40         4977  
22 40     40   183194 use Perl::Critic::Utils;
  40         102  
  40         761  
23 40     40   36349 use Perl::Critic::Pulp::Utils;
  40         92  
  40         1548  
24 40     40   275 use version (); # but don't import qv()
  40         135  
  40         1797  
25              
26             our $VERSION = 99;
27              
28 40     40   253 use constant supported_parameters => ();
  40         107  
  40         2757  
29 40     40   255 use constant default_severity => $Perl::Critic::Utils::SEVERITY_MEDIUM;
  40         105  
  40         2653  
30 40     40   312 use constant default_themes => qw(pulp bugs);
  40         97  
  40         2449  
31 40     40   264 use constant applies_to => 'PPI::Statement::Include';
  40         122  
  40         10064  
32              
33             sub violates {
34 16     16 1 561084 my ($self, $elem, $document) = @_;
35              
36 16 50       76 defined($elem->module) || return; # if a "use 5.005" etc
37 16   50     534 my $arg = $elem->schild(2) || return; # if a "use Foo" with no args
38 16 100       351 $arg->isa('PPI::Token::Quote') || return;
39 6 100       24 elem_is_last_of_statement($arg) || return;
40              
41             # This is a strict match of what a module version number is like.
42             # Previously looser forms like '.500' were matched too, but of course
43             # unquoting that doesn't give something that's checked by perl itself.
44             # There don't seem to be forms like .500 used in practice, so don't think
45             # it's important.
46             #
47 5         124 my $str = $arg->string;
48 5 100       76 $str =~ $Perl::Critic::Pulp::Utils::use_module_version_number_re
49             or return;
50              
51 4         22 return $self->violation
52             ("Don't use a quoted string version number in a \"use\" statement",
53             '',
54             $arg);
55             }
56              
57             # return true if $elem is the last thing in its statement, apart from an
58             # optional terminating ";"
59             #
60             sub elem_is_last_of_statement {
61 6     6 0 14 my ($elem) = @_;
62 6         34 my $next = $elem->snext_sibling;
63 6   66     209 return (! $next
64             || ($next->isa('PPI::Token::Structure')
65             && $next eq ';'
66             && ! $next->snext_sibling));
67             }
68              
69             1;
70             __END__
71              
72             =for stopwords builtin arg ok Ryde representable
73              
74             =head1 NAME
75              
76             Perl::Critic::Policy::Modules::ProhibitUseQuotedVersion - avoid quoted version number string in a "use" statement
77              
78             =head1 DESCRIPTION
79              
80             This policy is part of the L<C<Perl::Critic::Pulp>|Perl::Critic::Pulp>
81             add-on. It asks you not to quote a version number string as the sole
82             argument to a C<use> or C<no> statement.
83              
84             use Foo::Bar '1.50'; # bad
85             use Foo::Bar 1.50; # ok
86              
87             no Abc::Def '2.000_010'; # bad
88             no Abc::Def 2.000_010; # ok
89              
90             The unquoted form uses Perl's builtin module version check (Perl 5.004 up)
91             and is always enforced. The quoted form is passed to the module's
92             C<import()> and relies on it to do the check. If there's no C<import()>
93             then the quoted form is silently ignored.
94              
95             L<C<Exporter>|Exporter> as used by many modules provides an C<import()>
96             which checks a version number arg, so those modules are fine. But the idea
97             of this policy is to do what works always and on that basis is under the
98             "bugs" theme (see L<Perl::Critic/POLICY THEMES>).
99              
100             The builtin module version check is new in Perl 5.004. For earlier versions
101             both forms behave the same, with the string or number going through to the
102             module C<import> and so may or may not be checked. But even in code
103             supporting older Perl it's good to write the unquoted number so later Perl
104             will be certain to enforce it.
105              
106             The policy only applies to a single number string argument, anything else is
107             taken to be a module parameters.
108              
109             no Abc::Def '123', 'ABC'; # ok
110             use lib '..'; # ok
111              
112             If you're a bit nervous about unquoting because floating point version
113             numbers are often not exactly representable in binary, well, yes, that's
114             true, but in practice it works, either by converting the same way everywhere
115             in the program or by treated as a string to the C<version.pm> module anyway.
116              
117             =head2 Disabling
118              
119             If you're confident about the C<import()> in modules you use and prefer the
120             string form you can always disable C<ProhibitUseQuotedVersion> from your
121             F<.perlcriticrc> in the usual way (see L<Perl::Critic/CONFIGURATION>),
122              
123             [-Modules::ProhibitUseQuotedVersion]
124              
125             =head1 SEE ALSO
126              
127             L<Perl::Critic::Pulp>, L<Perl::Critic>
128              
129             L<Perl::Critic::Policy::ValuesAndExpressions::ProhibitVersionStrings>
130              
131             =head1 HOME PAGE
132              
133             L<http://user42.tuxfamily.org/perl-critic-pulp/index.html>
134              
135             =head1 COPYRIGHT
136              
137             Copyright 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019, 2021 Kevin Ryde
138              
139             Perl-Critic-Pulp is free software; you can redistribute it and/or modify it
140             under the terms of the GNU General Public License as published by the Free
141             Software Foundation; either version 3, or (at your option) any later
142             version.
143              
144             Perl-Critic-Pulp is distributed in the hope that it will be useful, but
145             WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
146             or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
147             more details.
148              
149             You should have received a copy of the GNU General Public License along with
150             Perl-Critic-Pulp. If not, see <http://www.gnu.org/licenses/>.
151              
152             =cut