File Coverage

blib/lib/Perl/Critic/Policy/ValuesAndExpressions/RequireConstantVersion.pm
Criterion Covered Total %
statement 92 99 92.9
branch 59 78 75.6
condition 24 60 40.0
subroutine 19 20 95.0
pod 4 5 80.0
total 198 262 75.5


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion;
2              
3 40     40   28437 use 5.010001;
  40         151  
4 40     40   258 use strict;
  40         105  
  40         882  
5 40     40   202 use warnings;
  40         87  
  40         1140  
6              
7 40     40   251 use Carp;
  40         106  
  40         2815  
8 40     40   320 use English qw(-no_match_vars);
  40         103  
  40         399  
9 40         2086 use Perl::Critic::Utils qw<
10             :booleans :characters :classification :data_conversion :language
11             :severities
12 40     40   16239 >;
  40         101  
13 40         2618 use Perl::Critic::Utils::PPI qw{
14             is_ppi_constant_element
15             get_next_element_in_same_simple_statement
16             get_previous_module_used_on_same_line
17 40     40   24630 };
  40         107  
18 40     40   289 use Readonly;
  40         122  
  40         2097  
19              
20 40     40   270 use parent 'Perl::Critic::Policy';
  40         114  
  40         222  
21              
22             our $VERSION = '1.148';
23              
24             #-----------------------------------------------------------------------------
25              
26             Readonly::Scalar my $BIND_REGEX => q<=~>;
27             Readonly::Scalar my $DOLLAR => q<$>;
28             # All uses of the $DOLLAR variable below are to prevent false failures in
29             # xt/93_version.t.
30             Readonly::Scalar my $QV => q<qv>;
31             Readonly::Scalar my $VERSION_MODULE => q<version>;
32             Readonly::Scalar my $VERSION_VARIABLE => $DOLLAR . q<VERSION>;
33              
34             # Operators which would make a new value our of our $VERSION, and therefore
35             # not modify it. I'm sure this list is not exhaustive. The logical operators
36             # generally do not qualify for this list. At least, I think not.
37             Readonly::Hash my %OPERATOR_WHICH_MAKES_NEW_VALUE => hashify( qw{
38             = . + - * ** / % ^ ~ & | > < == != >= <= eq ne gt lt ge le
39             } );
40              
41             Readonly::Scalar my $DESC => $DOLLAR . q<VERSION value must be a constant>;
42             Readonly::Scalar my $EXPL => qq<Computed ${DOLLAR}VERSION may tie the code to a single repository, or cause spooky action from a distance>;
43              
44             #-----------------------------------------------------------------------------
45              
46             sub supported_parameters { return (
47             {
48 100     100 0 2220 name => 'allow_version_without_use_on_same_line',
49             description =>
50             q{Allow qv() and version->new() without a 'use version' on the same line.},
51             default_string => $FALSE,
52             behavior => 'boolean',
53             }
54             );
55             }
56 203     203 1 779 sub default_severity { return $SEVERITY_LOW }
57 74     74 1 304 sub default_themes { return qw( core maintenance ) }
58 40     40 1 149 sub applies_to { return 'PPI::Token::Symbol' }
59              
60             #-----------------------------------------------------------------------------
61              
62             sub violates {
63 389     389 1 837 my ( $self, $elem, $doc ) = @_;
64              
65             # Any variable other than $VERSION is ignored.
66 389 100       989 return if $VERSION_VARIABLE ne $elem->content();
67              
68             # Get the next thing (presumably an operator) after $VERSION. The $VERSION
69             # might be in a list, so if we get nothing we move upwards until we hit a
70             # simple statement. If we have nothing at this point, we do not understand
71             # the code, and so we return.
72 219         1189 my $operator;
73             return if
74 219 50       663 not $operator = get_next_element_in_same_simple_statement( $elem );
75              
76             # If the next operator is a regex binding, and its other operand is a
77             # substitution operator, it is an attempt to modify $VERSION, so we
78             # return an error to that effect.
79 219 100       7056 return $self->violation( $DESC, $EXPL, $elem )
80             if $self->_validate_operator_bind_regex( $operator, $elem );
81              
82             # If the presumptive operator is not an assignment operator of some sort,
83             # we are not modifying $VERSION at all, and so we just return.
84 218 100       1603 return if not $operator = _check_for_assignment_operator( $operator );
85              
86             # If there is no operand to the right of the assignment, we do not
87             # understand the code; simply return.
88 210         2111 my $value;
89 210 50       597 return if not $value = $operator->snext_sibling();
90              
91             # If the value is symbol '$VERSION', just return as we will see it again
92             # later.
93             return if
94 210 100 100     6563 $value->isa( 'PPI::Token::Symbol' )
95             and $value->content() eq $VERSION_VARIABLE;
96              
97             # If the value is a word, there are a number of acceptable things it could
98             # be. Check for these. If there was a problem, return it.
99 208         805 $value = $self->_validate_word_token( $elem, $value );
100 208 50       812 return $value if $value->isa( 'Perl::Critic::Exception' );
101              
102             # If the value is anything but a constant, we cry foul.
103 208 100       696 return $self->violation( $DESC, $EXPL, $elem )
104             if not is_ppi_constant_element( $value );
105              
106             # If we have nothing after the value, it is OK.
107 109         512 my $structure;
108             return if
109 109 50       297 not $structure = get_next_element_in_same_simple_statement( $value );
110              
111             # If we have a semicolon after the value, it is OK.
112 109 100       3373 return if $SCOLON eq $structure->content();
113              
114             # If there is anything else after the value, we cry foul.
115 22         196 return $self->violation( $DESC, $EXPL, $elem );
116             }
117              
118             #-----------------------------------------------------------------------------
119              
120             # Check if the element is an assignment operator.
121              
122             sub _check_for_assignment_operator {
123 218     218   472 my ( $operator ) = @_;
124              
125 218 100       828 return if not $operator->isa( 'PPI::Token::Operator' );
126 217 100       544 return $operator if is_assignment_operator($operator->content());
127 7         81 return;
128             }
129              
130             #-----------------------------------------------------------------------------
131              
132             # Validate a bind_regex ('=~') operator appearing after $VERSION. We return
133             # true if the operator is in fact '=~', and its next sibling isa
134             # PPI::Token::Regexp::Substitute. Otherwise we return false.
135              
136             sub _validate_operator_bind_regex {
137 219     219   528 my ( $self, $operator, $elem ) = @_;
138              
139             # We are not interested in anything but '=~ s/../../'.
140 219 100       624 return if $BIND_REGEX ne $operator->content();
141 6         37 my $operand;
142 6 50       20 return if not $operand = $operator->snext_sibling();
143 6 50       175 return if not $operand->isa( 'PPI::Token::Regexp::Substitute' );
144              
145             # The substitution is OK if it is of the form
146             # '($var = $VERSION) =~ s/../../'.
147              
148             # We can't look like the desired form if we have a next sig. sib.
149 6 100       20 return $TRUE if $elem->snext_sibling();
150              
151             # We can't look like the desired form if we are not in a list.
152 5         150 my $containing_list;
153 5 50 33     17 $containing_list = $elem->parent()
      33        
      33        
154             and $containing_list->isa( 'PPI::Statement' )
155             and $containing_list = $containing_list->parent()
156             and $containing_list->isa( 'PPI::Structure::List' )
157             or return $TRUE;
158              
159             # If we have no prior element, we're ( $VERSION ) =~ s/../../,
160             # which flunks.
161 5 50       151 my $prior = $elem->sprevious_sibling() or return $TRUE;
162              
163             # If the prior element is an operator which makes a new value, we pass.
164             return if $prior->isa( 'PPI::Token::Operator' )
165 5 100 66     197 && $OPERATOR_WHICH_MAKES_NEW_VALUE{ $prior->content() };
166              
167             # Now things get complicated, as RT #55600 shows. We need to grub through
168             # the entire list, looking for something that looks like a subroutine
169             # call, but without parens around the argument list. This catches the
170             # ticket's case, which was
171             # ( $foo = sprintf '%s/%s', __PACKAGE__, $VERSION ) =~ s/../../.
172 3         43 my $current = $prior;
173 3         10 while( $prior = $current->sprevious_sibling() ) {
174 11 100       353 $prior->isa( 'PPI::Token::Word' ) or next;
175 5 100       23 is_function_call( $prior) or next;
176             # If this function has its own argument list, we need to keep looking;
177             # otherwise we have found a function with no parens, and we can
178             # return.
179 2 50       13 $current->isa( 'PPI::Structure::List' )
180             or return;
181             } continue {
182 9         70 $current = $prior;
183             }
184              
185             # Maybe the whole list was arguments for a subroutine or method call.
186 1 50       21 $prior = $containing_list->sprevious_sibling()
187             or return $TRUE;
188 1 50       29 if ( $prior->isa( 'PPI::Token::Word' ) ) {
189 1 50       6 return if is_method_call( $prior );
190 1 50       4 return if is_function_call( $prior );
191             }
192              
193             # Anything left is presumed a violation.
194 0         0 return $TRUE;
195             }
196              
197             #-----------------------------------------------------------------------------
198              
199             # Validating a PPI::Token::Word is a complicated business, so we split it out
200             # into its own subroutine. The $elem is to be used in forming the error
201             # message, and the $value is the PPI::Token::Word we just encountered. The
202             # return is either a PPI::Element for further analysis, or a
203             # Perl::Critic::Exception to be returned.
204              
205             sub _validate_word_token {
206 208     208   547 my ( $self, $elem, $value ) = @_;
207              
208 208 100       777 if ( $value->isa( 'PPI::Token::Word' ) ) {
209 75         183 my $content = $value->content();
210              
211             # If the word is of the form 'v\d+' it may be the first portion of a
212             # misparsed (by PPI) v-string. It is really a v-string if the next
213             # element is a number. Unless v-strings are allowed, we return an
214             # error.
215 75 50       624 if ( $content =~ m/ \A v \d+ \z /smx ) {
    100          
    100          
216 0         0 $value = $self->_validate_word_vstring( $elem, $value );
217             }
218             elsif ( $QV eq $content ) {
219             # If the word is 'qv' we suspect use of the version module. If
220             # 'use version' appears on the same line, _and_ the remainder of
221             # the expression is of the form '(value)', we extract the value
222             # for further analysis.
223              
224 10         55 $value = $self->_validate_word_qv( $elem, $value );
225             }
226             elsif ( $VERSION_MODULE eq $content ) {
227             # If the word is 'version' we suspect use of the version module.
228             # Check to see if it is properly used.
229 8         36 $value = $self->_validate_word_version( $elem, $value );
230             }
231             }
232              
233 208         1450 return $value;
234             }
235              
236             #-----------------------------------------------------------------------------
237              
238             # Validate $VERSION = v1.2.3;
239             # Note that this is needed because PPI mis-parses the 'v1.2.3' construct into
240             # a word ('v1') and a number of some sort ('.2.3'). This method should only be
241             # called if it is already known that the $value is a PPI::Token::Word matching
242             # m/ \A v \d+ \z /smx;
243              
244             sub _validate_word_vstring {
245 0     0   0 my ( $self, $elem, $value ) = @_;
246              
247             # Check for the second part of the mis-parsed v-string, flunking if it is
248             # not found.
249 0         0 my $next;
250 0 0 0     0 return $self->violation( $DESC, $EXPL, $elem )
251             if
252             not $next = $value->snext_sibling()
253             or not $next->isa( 'PPI::Token::Number' );
254              
255             # Return the second part of the v-string for further analysis.
256 0         0 return $next;
257             }
258              
259             #-----------------------------------------------------------------------------
260              
261             # Validate $VERSION = qv();
262              
263             sub _validate_word_qv {
264 10     10   40 my ( $self, $elem, $value ) = @_;
265              
266             # Unless we are specifically allowing this construction without the
267             # 'use version;' on the same line, check for it and flunk if we do not
268             # find it.
269             $self->{_allow_version_without_use_on_same_line}
270 10 100       45 or do {
271 9         22 my $module;
272 9 100       32 return $self->violation( $DESC, $EXPL, $elem )
273             if not
274             $module = get_previous_module_used_on_same_line($value);
275 7 50       157 return $self->violation( $DESC, $EXPL, $elem )
276             if $VERSION_MODULE ne $module->content();
277             };
278              
279             # Dig out the first argument of 'qv()', flunking if we can not find it.
280 8         48 my $next;
281 8 100 33     32 return $self->violation( $DESC, $EXPL, $elem )
      33        
      66        
      66        
282             if not (
283             $next = $value->snext_sibling()
284             and $next->isa( 'PPI::Structure::List' )
285             and $next = $next->schild( 0 )
286             and $next->isa( 'PPI::Statement::Expression' )
287             and $next = $next->schild( 0 )
288             );
289              
290             # Return the qv() argument for further analysis.
291 7         499 return $next;
292             }
293              
294             #-----------------------------------------------------------------------------
295              
296             # Validate $VERSION = version->new();
297              
298             # TODO: Fix this EVIL dual-purpose return value. This is ugggggleeeee.
299             sub _validate_word_version {
300 8     8   24 my ( $self, $elem, $value ) = @_;
301              
302             # Unless we are specifically allowing this construction without the
303             # 'use version;' on the same line, check for it and flunk if we do not
304             # find it.
305             $self->{_allow_version_without_use_on_same_line}
306 8 100       33 or do {
307 6         13 my $module;
308 6 100       25 return $self->violation( $DESC, $EXPL, $elem )
309             if not
310             $module = get_previous_module_used_on_same_line($value);
311 2 50       46 return $self->violation( $DESC, $EXPL, $elem )
312             if $VERSION_MODULE ne $module->content();
313             };
314              
315             # Dig out the first argument of '->new()', flunking if we can not find it.
316 4         89 my $next;
317 4 50 33     17 return $next if
      33        
      33        
      33        
      33        
      33        
      33        
      33        
      33        
      33        
318             $next = $value->snext_sibling()
319             and $next->isa( 'PPI::Token::Operator' )
320             and q{->} eq $next->content()
321             and $next = $next->snext_sibling()
322             and $next->isa( 'PPI::Token::Word' )
323             and q{new} eq $next->content()
324             and $next = $next->snext_sibling()
325             and $next->isa( 'PPI::Structure::List' )
326             and $next = $next->schild( 0 )
327             and $next->isa( 'PPI::Statement::Expression' )
328             and $next = $next->schild( 0 );
329              
330 0           return $self->violation( $DESC, $EXPL, $elem );
331             }
332              
333             1;
334              
335             __END__
336              
337             #-----------------------------------------------------------------------------
338              
339             =pod
340              
341             =head1 NAME
342              
343             Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion - Require $VERSION to be a constant rather than a computed value.
344              
345              
346             =head1 AFFILIATION
347              
348             This Policy is part of the core L<Perl::Critic|Perl::Critic>
349             distribution.
350              
351              
352             =head1 DESCRIPTION
353              
354             The $VERSION variable of a module should be a simple constant - either a
355             number, a single-quotish string, or a 'use version' object. In the latter case
356             the 'use version;' must appear on the same line as the object construction.
357              
358             Computing the version has problems of various severities.
359              
360             The most benign violation is computing the version from (e.g.) a Subversion
361             revision number:
362              
363             our ($VERSION) = q$REVISION: 42$ =~ /(\d+)/;
364              
365             The problem here is that the version is tied to a single repository. The code
366             can not be moved to another repository (even of the same type) without
367             changing its version, possibly in the wrong direction.
368              
369             This policy accepts v-strings (C<v1.2.3> or just plain C<1.2.3>), since these
370             are already flagged by
371             L<Perl::Critic::Policy::ValuesAndExpressions::ProhibitVersionStrings|Perl::Critic::Policy::ValuesAndExpressions::ProhibitVersionStrings>.
372              
373              
374             =head1 CONFIGURATION
375              
376             The proper way to set a module's $VERSION to a C<version> object is to
377             C<use version;> on the same line of code that assigns the value of $VERSION.
378             That way, L<ExtUtils::MakeMaker|ExtUtils::MakeMaker> and
379             L<Module::Build|Module::Build> can extract the version when packaging the
380             module for CPAN. By default, this policy declares an error if this is not
381             done.
382              
383             Should you wish to allow version objects without loading the version module on
384             the same line, add the following to your configuration file:
385              
386             [ValuesAndExpressions::RequireConstantVersion]
387             allow_version_without_use_on_same_line = 1
388              
389              
390             =head1 CAVEATS
391              
392             There will be false negatives if the $VERSION appears on the left-hand side of
393             a list assignment that assigns to more than one variable, or to C<undef>.
394              
395             There may be false positives if the $VERSION is assigned the value of a here
396             document. This will probably remain the case until
397             L<PPI::Token::HereDoc|PPI::Token::HereDoc> acquires the relevant portions of
398             the L<PPI::Token::Quote|PPI::Token::Quote> interface.
399              
400             There will be false positives if $VERSION is assigned the value of a constant
401             created by the L<Readonly|Readonly> module or the L<constant|constant> pragma,
402             because the necessary infrastructure appears not to exist, and the author of
403             the present module lacked the knowledge/expertise/gumption to put it in place.
404              
405             Currently the idiom
406              
407             our $VERSION = '1.005_05';
408             $VERSION = eval $VERSION;
409              
410             will produce a violation on the second line of the example.
411              
412              
413             =head1 AUTHOR
414              
415             Thomas R. Wyant, III F<wyant at cpan dot org>
416              
417              
418             =head1 COPYRIGHT
419              
420             Copyright (c) 2009-2011 Tom Wyant.
421              
422             This program is free software; you can redistribute it and/or modify
423             it under the same terms as Perl itself. The full text of this license
424             can be found in the LICENSE file included with this module
425              
426             =cut
427              
428             # Local Variables:
429             # mode: cperl
430             # cperl-indent-level: 4
431             # fill-column: 78
432             # indent-tabs-mode: nil
433             # c-indentation-style: bsd
434             # End:
435             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :