| Filename | /Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/Perl/Critic/Policy/ValuesAndExpressions/RequireConstantVersion.pm |
| Statements | Executed 30 statements in 1.19ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 16µs | 33µs | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@25 |
| 1 | 1 | 1 | 16µs | 16µs | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@10 |
| 1 | 1 | 1 | 16µs | 18µs | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::supported_parameters |
| 1 | 1 | 1 | 8µs | 37µs | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@20 |
| 1 | 1 | 1 | 8µs | 44µs | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@14 |
| 1 | 1 | 1 | 8µs | 384µs | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@15 |
| 1 | 1 | 1 | 8µs | 678µs | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@16 |
| 1 | 1 | 1 | 7µs | 76µs | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@27 |
| 1 | 1 | 1 | 7µs | 10µs | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@12 |
| 1 | 1 | 1 | 7µs | 18µs | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@11 |
| 1 | 1 | 1 | 6µs | 7µs | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::default_severity |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::_check_for_assignment_operator |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::_validate_operator_bind_regex |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::_validate_word_qv |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::_validate_word_token |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::_validate_word_version |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::_validate_word_vstring |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::applies_to |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::default_themes |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::violates |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | ############################################################################## | ||||
| 2 | # $URL$ | ||||
| 3 | # $Date$ | ||||
| 4 | # $Author$ | ||||
| 5 | # $Revision$ | ||||
| 6 | ############################################################################## | ||||
| 7 | |||||
| 8 | package Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion; | ||||
| 9 | |||||
| 10 | 2 | 38µs | 1 | 16µs | # spent 16µs within Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@10 which was called:
# once (16µs+0s) by Module::Pluggable::Object::_require at line 10 # spent 16µs making 1 call to Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@10 |
| 11 | 2 | 19µs | 2 | 28µs | # spent 18µs (7+11) within Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@11 which was called:
# once (7µs+11µs) by Module::Pluggable::Object::_require at line 11 # spent 18µs making 1 call to Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@11
# spent 11µs making 1 call to strict::import |
| 12 | 2 | 22µs | 2 | 14µs | # spent 10µs (7+3) within Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@12 which was called:
# once (7µs+3µs) by Module::Pluggable::Object::_require at line 12 # spent 10µs making 1 call to Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@12
# spent 4µs making 1 call to warnings::import |
| 13 | |||||
| 14 | 2 | 22µs | 2 | 81µs | # spent 44µs (8+36) within Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@14 which was called:
# once (8µs+36µs) by Module::Pluggable::Object::_require at line 14 # spent 44µs making 1 call to Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@14
# spent 36µs making 1 call to Exporter::import |
| 15 | 2 | 27µs | 2 | 760µs | # spent 384µs (8+376) within Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@15 which was called:
# once (8µs+376µs) by Module::Pluggable::Object::_require at line 15 # spent 384µs making 1 call to Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@15
# spent 376µs making 1 call to English::import |
| 16 | 1 | 300ns | # spent 678µs (8+670) within Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@16 which was called:
# once (8µs+670µs) by Module::Pluggable::Object::_require at line 19 | ||
| 17 | :booleans :characters :classification :data_conversion :language | ||||
| 18 | :severities | ||||
| 19 | 1 | 27µs | 2 | 1.35ms | >; # spent 678µs making 1 call to Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@16
# spent 670µs making 1 call to Exporter::import |
| 20 | 1 | 400ns | # spent 37µs (8+29) within Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@20 which was called:
# once (8µs+29µs) by Module::Pluggable::Object::_require at line 24 | ||
| 21 | is_ppi_constant_element | ||||
| 22 | get_next_element_in_same_simple_statement | ||||
| 23 | get_previous_module_used_on_same_line | ||||
| 24 | 1 | 20µs | 2 | 67µs | }; # spent 37µs making 1 call to Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@20
# spent 29µs making 1 call to Exporter::import |
| 25 | 2 | 22µs | 2 | 50µs | # spent 33µs (16+17) within Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@25 which was called:
# once (16µs+17µs) by Module::Pluggable::Object::_require at line 25 # spent 33µs making 1 call to Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@25
# spent 17µs making 1 call to Exporter::import |
| 26 | |||||
| 27 | 2 | 952µs | 2 | 145µs | # spent 76µs (7+69) within Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@27 which was called:
# once (7µs+69µs) by Module::Pluggable::Object::_require at line 27 # spent 76µs making 1 call to Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::BEGIN@27
# spent 69µs making 1 call to base::import |
| 28 | |||||
| 29 | 1 | 600ns | our $VERSION = '1.121'; | ||
| 30 | |||||
| 31 | #----------------------------------------------------------------------------- | ||||
| 32 | |||||
| 33 | 1 | 2µs | 1 | 30µs | Readonly::Scalar my $BIND_REGEX => q<=~>; # spent 30µs making 1 call to Readonly::Scalar |
| 34 | 1 | 900ns | 1 | 22µs | Readonly::Scalar my $DOLLAR => q<$>; # spent 22µs making 1 call to Readonly::Scalar |
| 35 | # All uses of the $DOLLAR variable below are to prevent false failures in | ||||
| 36 | # xt/author/93_version.t. | ||||
| 37 | 1 | 800ns | 1 | 20µs | Readonly::Scalar my $QV => q<qv>; # spent 20µs making 1 call to Readonly::Scalar |
| 38 | 1 | 800ns | 1 | 20µs | Readonly::Scalar my $VERSION_MODULE => q<version>; # spent 20µs making 1 call to Readonly::Scalar |
| 39 | 1 | 4µs | 2 | 22µs | Readonly::Scalar my $VERSION_VARIABLE => $DOLLAR . q<VERSION>; # spent 20µs making 1 call to Readonly::Scalar
# spent 1µs making 1 call to Readonly::Scalar::FETCH |
| 40 | |||||
| 41 | # Operators which would make a new value our of our $VERSION, and therefore | ||||
| 42 | # not modify it. I'm sure this list is not exhaustive. The logical operators | ||||
| 43 | # generally do not qualify for this list. At least, I think not. | ||||
| 44 | 1 | 5µs | 2 | 52µs | Readonly::Hash my %OPERATOR_WHICH_MAKES_NEW_VALUE => hashify( qw{ # spent 44µs making 1 call to Readonly::Hash
# spent 7µs making 1 call to Perl::Critic::Utils::hashify |
| 45 | = . + - * ** / % ^ ~ & | > < == != >= <= eq ne gt lt ge le | ||||
| 46 | } ); | ||||
| 47 | |||||
| 48 | 1 | 4µs | 2 | 22µs | Readonly::Scalar my $DESC => $DOLLAR . q<VERSION value must be a constant>; # spent 21µs making 1 call to Readonly::Scalar
# spent 1µs making 1 call to Readonly::Scalar::FETCH |
| 49 | 1 | 3µs | 2 | 21µs | Readonly::Scalar my $EXPL => qq<Computed ${DOLLAR}VERSION may tie the code to a single repository, or cause spooky action from a distance>; # spent 20µs making 1 call to Readonly::Scalar
# spent 1µs making 1 call to Readonly::Scalar::FETCH |
| 50 | |||||
| 51 | #----------------------------------------------------------------------------- | ||||
| 52 | |||||
| 53 | # spent 18µs (16+3) within Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::supported_parameters which was called:
# once (16µs+3µs) by Perl::Critic::Policy::new at line 88 of Perl/Critic/Policy.pm | ||||
| 54 | { | ||||
| 55 | 1 | 12µs | 2 | 3µs | name => 'allow_version_without_use_on_same_line', # spent 3µs making 2 calls to Readonly::Scalar::FETCH, avg 1µs/call |
| 56 | description => | ||||
| 57 | q{Allow qv() and version->new() without a 'use version' on the same line.}, | ||||
| 58 | default_string => $FALSE, | ||||
| 59 | behavior => 'boolean', | ||||
| 60 | } | ||||
| 61 | ); | ||||
| 62 | } | ||||
| 63 | 1 | 1µs | # spent 7µs (6+1) within Perl::Critic::Policy::ValuesAndExpressions::RequireConstantVersion::default_severity which was called:
# once (6µs+1µs) by Perl::Critic::Policy::get_severity at line 331 of Perl/Critic/Policy.pm | ||
| 64 | sub default_themes { return qw( core maintenance ) } | ||||
| 65 | sub applies_to { return 'PPI::Token::Symbol' } | ||||
| 66 | |||||
| 67 | #----------------------------------------------------------------------------- | ||||
| 68 | |||||
| 69 | sub violates { | ||||
| 70 | my ( $self, $elem, $doc ) = @_; | ||||
| 71 | |||||
| 72 | # Any variable other than $VERSION is ignored. | ||||
| 73 | return if $VERSION_VARIABLE ne $elem->content(); | ||||
| 74 | |||||
| 75 | # Get the next thing (presumably an operator) after $VERSION. The $VERSION | ||||
| 76 | # might be in a list, so if we get nothing we move upwards until we hit a | ||||
| 77 | # simple statement. If we have nothing at this point, we do not understand | ||||
| 78 | # the code, and so we return. | ||||
| 79 | my $operator; | ||||
| 80 | return if | ||||
| 81 | not $operator = get_next_element_in_same_simple_statement( $elem ); | ||||
| 82 | |||||
| 83 | # If the next operator is a regex binding, and its other operand is a | ||||
| 84 | # substitution operator, it is an attempt to modify $VERSION, so we | ||||
| 85 | # return an error to that effect. | ||||
| 86 | return $self->violation( $DESC, $EXPL, $elem ) | ||||
| 87 | if $self->_validate_operator_bind_regex( $operator, $elem ); | ||||
| 88 | |||||
| 89 | # If the presumptive operator is not an assignment operator of some sort, | ||||
| 90 | # we are not modifying $VERSION at all, and so we just return. | ||||
| 91 | return if not $operator = _check_for_assignment_operator( $operator ); | ||||
| 92 | |||||
| 93 | # If there is no operand to the right of the assignment, we do not | ||||
| 94 | # understand the code; simply return. | ||||
| 95 | my $value; | ||||
| 96 | return if not $value = $operator->snext_sibling(); | ||||
| 97 | |||||
| 98 | # If the value is symbol '$VERSION', just return as we will see it again | ||||
| 99 | # later. | ||||
| 100 | return if | ||||
| 101 | $value->isa( 'PPI::Token::Symbol' ) | ||||
| 102 | and $value->content() eq $VERSION_VARIABLE; | ||||
| 103 | |||||
| 104 | # If the value is a word, there are a number of acceptable things it could | ||||
| 105 | # be. Check for these. If there was a problem, return it. | ||||
| 106 | $value = $self->_validate_word_token( $elem, $value ); | ||||
| 107 | return $value if $value->isa( 'Perl::Critic::Exception' ); | ||||
| 108 | |||||
| 109 | # If the value is anything but a constant, we cry foul. | ||||
| 110 | return $self->violation( $DESC, $EXPL, $elem ) | ||||
| 111 | if not is_ppi_constant_element( $value ); | ||||
| 112 | |||||
| 113 | # If we have nothing after the value, it is OK. | ||||
| 114 | my $structure; | ||||
| 115 | return if | ||||
| 116 | not $structure = get_next_element_in_same_simple_statement( $value ); | ||||
| 117 | |||||
| 118 | # If we have a semicolon after the value, it is OK. | ||||
| 119 | return if $SCOLON eq $structure->content(); | ||||
| 120 | |||||
| 121 | # If there is anything else after the value, we cry foul. | ||||
| 122 | return $self->violation( $DESC, $EXPL, $elem ); | ||||
| 123 | } | ||||
| 124 | |||||
| 125 | #----------------------------------------------------------------------------- | ||||
| 126 | |||||
| 127 | # Check for an assignment operator. This is made more complicated by the fact | ||||
| 128 | # that PPI parses things like '||=' as two PPI::Token::Operators: '||' and | ||||
| 129 | # '='. So we take the first presumptive operator as an argument. If it is not | ||||
| 130 | # a PPI::Token::Operator, we return. If it's '=', we return it. If it is any | ||||
| 131 | # other operator, we see if the next significant token is '=', and if so | ||||
| 132 | # return that. | ||||
| 133 | |||||
| 134 | sub _check_for_assignment_operator { | ||||
| 135 | my ( $operator ) = @_; | ||||
| 136 | |||||
| 137 | return if not $operator->isa( 'PPI::Token::Operator' ); | ||||
| 138 | return $operator if $EQUAL eq $operator->content(); | ||||
| 139 | |||||
| 140 | my $next; | ||||
| 141 | return if not $next = $operator->snext_sibling(); | ||||
| 142 | return if not $next->isa( 'PPI::Token::Operator' ); | ||||
| 143 | return $next if $EQUAL eq $next->content(); | ||||
| 144 | |||||
| 145 | return; | ||||
| 146 | } | ||||
| 147 | |||||
| 148 | #----------------------------------------------------------------------------- | ||||
| 149 | |||||
| 150 | # Validate a bind_regex ('=~') operator appearing after $VERSION. We return | ||||
| 151 | # true if the operator is in fact '=~', and its next sibling isa | ||||
| 152 | # PPI::Token::Regexp::Substitute. Otherwise we return false. | ||||
| 153 | |||||
| 154 | sub _validate_operator_bind_regex { | ||||
| 155 | my ( $self, $operator, $elem ) = @_; | ||||
| 156 | |||||
| 157 | # We are not interested in anything but '=~ s/../../'. | ||||
| 158 | return if $BIND_REGEX ne $operator->content(); | ||||
| 159 | my $operand; | ||||
| 160 | return if not $operand = $operator->snext_sibling(); | ||||
| 161 | return if not $operand->isa( 'PPI::Token::Regexp::Substitute' ); | ||||
| 162 | |||||
| 163 | # The substitution is OK if it is of the form | ||||
| 164 | # '($var = $VERSION) =~ s/../../'. | ||||
| 165 | |||||
| 166 | # We can't look like the desired form if we have a next sig. sib. | ||||
| 167 | return $TRUE if $elem->snext_sibling(); | ||||
| 168 | |||||
| 169 | # We can't look like the desired form if we are not in a list. | ||||
| 170 | my $containing_list; | ||||
| 171 | $containing_list = $elem->parent() | ||||
| 172 | and $containing_list->isa( 'PPI::Statement' ) | ||||
| 173 | and $containing_list = $containing_list->parent() | ||||
| 174 | and $containing_list->isa( 'PPI::Structure::List' ) | ||||
| 175 | or return $TRUE; | ||||
| 176 | |||||
| 177 | # If we have no prior element, we're ( $VERSION ) =~ s/../../, | ||||
| 178 | # which flunks. | ||||
| 179 | my $prior = $elem->sprevious_sibling() or return $TRUE; | ||||
| 180 | |||||
| 181 | # If the prior element is an operator which makes a new value, we pass. | ||||
| 182 | return if $prior->isa( 'PPI::Token::Operator' ) | ||||
| 183 | && $OPERATOR_WHICH_MAKES_NEW_VALUE{ $prior->content() }; | ||||
| 184 | |||||
| 185 | # Now things get complicated, as RT #55600 shows. We need to grub through | ||||
| 186 | # the entire list, looking for something that looks like a subroutine | ||||
| 187 | # call, but without parens around the argument list. This catches the | ||||
| 188 | # ticket's case, which was | ||||
| 189 | # ( $foo = sprintf '%s/%s', __PACKAGE__, $VERSION ) =~ s/../../. | ||||
| 190 | my $current = $prior; | ||||
| 191 | while( $prior = $current->sprevious_sibling() ) { | ||||
| 192 | $prior->isa( 'PPI::Token::Word' ) or next; | ||||
| 193 | is_function_call( $prior) or next; | ||||
| 194 | # If this function has its own argument list, we need to keep looking; | ||||
| 195 | # otherwise we have found a function with no parens, and we can | ||||
| 196 | # return. | ||||
| 197 | $current->isa( 'PPI::Structure::List' ) | ||||
| 198 | or return; | ||||
| 199 | } continue { | ||||
| 200 | $current = $prior; | ||||
| 201 | } | ||||
| 202 | |||||
| 203 | # Maybe the whole list was arguments for a subroutine or method call. | ||||
| 204 | $prior = $containing_list->sprevious_sibling() | ||||
| 205 | or return $TRUE; | ||||
| 206 | if ( $prior->isa( 'PPI::Token::Word' ) ) { | ||||
| 207 | return if is_method_call( $prior ); | ||||
| 208 | return if is_function_call( $prior ); | ||||
| 209 | } | ||||
| 210 | |||||
| 211 | # Anything left is presumed a violation. | ||||
| 212 | return $TRUE; | ||||
| 213 | } | ||||
| 214 | |||||
| 215 | #----------------------------------------------------------------------------- | ||||
| 216 | |||||
| 217 | # Validating a PPI::Token::Word is a complicated business, so we split it out | ||||
| 218 | # into its own subroutine. The $elem is to be used in forming the error | ||||
| 219 | # message, and the $value is the PPI::Token::Word we just encountered. The | ||||
| 220 | # return is either a PPI::Element for further analysis, or a | ||||
| 221 | # Perl::Critic::Exception to be returned. | ||||
| 222 | |||||
| 223 | sub _validate_word_token { | ||||
| 224 | my ( $self, $elem, $value ) = @_; | ||||
| 225 | |||||
| 226 | if ( $value->isa( 'PPI::Token::Word' ) ) { | ||||
| 227 | my $content = $value->content(); | ||||
| 228 | |||||
| 229 | # If the word is of the form 'v\d+' it may be the first portion of a | ||||
| 230 | # misparsed (by PPI) v-string. It is really a v-string if the next | ||||
| 231 | # element is a number. Unless v-strings are allowed, we return an | ||||
| 232 | # error. | ||||
| 233 | if ( $content =~ m/ \A v \d+ \z /smx ) { | ||||
| 234 | $value = $self->_validate_word_vstring( $elem, $value ); | ||||
| 235 | } | ||||
| 236 | elsif ( $QV eq $content ) { | ||||
| 237 | # If the word is 'qv' we suspect use of the version module. If | ||||
| 238 | # 'use version' appears on the same line, _and_ the remainder of | ||||
| 239 | # the expression is of the form '(value)', we extract the value | ||||
| 240 | # for further analysis. | ||||
| 241 | |||||
| 242 | $value = $self->_validate_word_qv( $elem, $value ); | ||||
| 243 | } | ||||
| 244 | elsif ( $VERSION_MODULE eq $content ) { | ||||
| 245 | # If the word is 'version' we suspect use of the version module. | ||||
| 246 | # Check to see if it is properly used. | ||||
| 247 | $value = $self->_validate_word_version( $elem, $value ); | ||||
| 248 | } | ||||
| 249 | } | ||||
| 250 | |||||
| 251 | return $value; | ||||
| 252 | } | ||||
| 253 | |||||
| 254 | #----------------------------------------------------------------------------- | ||||
| 255 | |||||
| 256 | # Validate $VERSION = v1.2.3; | ||||
| 257 | # Note that this is needed because PPI mis-parses the 'v1.2.3' construct into | ||||
| 258 | # a word ('v1') and a number of some sort ('.2.3'). This method should only be | ||||
| 259 | # called if it is already known that the $value is a PPI::Token::Word matching | ||||
| 260 | # m/ \A v \d+ \z /smx; | ||||
| 261 | |||||
| 262 | sub _validate_word_vstring { | ||||
| 263 | my ( $self, $elem, $value ) = @_; | ||||
| 264 | |||||
| 265 | # Check for the second part of the mis-parsed v-string, flunking if it is | ||||
| 266 | # not found. | ||||
| 267 | my $next; | ||||
| 268 | return $self->violation( $DESC, $EXPL, $elem ) | ||||
| 269 | if | ||||
| 270 | not $next = $value->snext_sibling() | ||||
| 271 | or not $next->isa( 'PPI::Token::Number' ); | ||||
| 272 | |||||
| 273 | # Return the second part of the v-string for further analysis. | ||||
| 274 | return $next; | ||||
| 275 | } | ||||
| 276 | |||||
| 277 | #----------------------------------------------------------------------------- | ||||
| 278 | |||||
| 279 | # Validate $VERSION = qv(); | ||||
| 280 | |||||
| 281 | sub _validate_word_qv { | ||||
| 282 | my ( $self, $elem, $value ) = @_; | ||||
| 283 | |||||
| 284 | # Unless we are specifically allowing this construction without the | ||||
| 285 | # 'use version;' on the same line, check for it and flunk if we do not | ||||
| 286 | # find it. | ||||
| 287 | $self->{_allow_version_without_use_on_same_line} | ||||
| 288 | or do { | ||||
| 289 | my $module; | ||||
| 290 | return $self->violation( $DESC, $EXPL, $elem ) | ||||
| 291 | if not | ||||
| 292 | $module = get_previous_module_used_on_same_line($value); | ||||
| 293 | return $self->violation( $DESC, $EXPL, $elem ) | ||||
| 294 | if $VERSION_MODULE ne $module->content(); | ||||
| 295 | }; | ||||
| 296 | |||||
| 297 | # Dig out the first argument of 'qv()', flunking if we can not find it. | ||||
| 298 | my $next; | ||||
| 299 | return $self->violation( $DESC, $EXPL, $elem ) | ||||
| 300 | if not ( | ||||
| 301 | $next = $value->snext_sibling() | ||||
| 302 | and $next->isa( 'PPI::Structure::List' ) | ||||
| 303 | and $next = $next->schild( 0 ) | ||||
| 304 | and $next->isa( 'PPI::Statement::Expression' ) | ||||
| 305 | and $next = $next->schild( 0 ) | ||||
| 306 | ); | ||||
| 307 | |||||
| 308 | # Return the qv() argument for further analysis. | ||||
| 309 | return $next; | ||||
| 310 | } | ||||
| 311 | |||||
| 312 | #----------------------------------------------------------------------------- | ||||
| 313 | |||||
| 314 | # Validate $VERSION = version->new(); | ||||
| 315 | |||||
| 316 | # TODO: Fix this EVIL dual-purpose return value. This is ugggggleeeee. | ||||
| 317 | sub _validate_word_version { | ||||
| 318 | my ( $self, $elem, $value ) = @_; | ||||
| 319 | |||||
| 320 | # Unless we are specifically allowing this construction without the | ||||
| 321 | # 'use version;' on the same line, check for it and flunk if we do not | ||||
| 322 | # find it. | ||||
| 323 | $self->{_allow_version_without_use_on_same_line} | ||||
| 324 | or do { | ||||
| 325 | my $module; | ||||
| 326 | return $self->violation( $DESC, $EXPL, $elem ) | ||||
| 327 | if not | ||||
| 328 | $module = get_previous_module_used_on_same_line($value); | ||||
| 329 | return $self->violation( $DESC, $EXPL, $elem ) | ||||
| 330 | if $VERSION_MODULE ne $module->content(); | ||||
| 331 | }; | ||||
| 332 | |||||
| 333 | # Dig out the first argument of '->new()', flunking if we can not find it. | ||||
| 334 | my $next; | ||||
| 335 | return $next if | ||||
| 336 | $next = $value->snext_sibling() | ||||
| 337 | and $next->isa( 'PPI::Token::Operator' ) | ||||
| 338 | and q{->} eq $next->content() | ||||
| 339 | and $next = $next->snext_sibling() | ||||
| 340 | and $next->isa( 'PPI::Token::Word' ) | ||||
| 341 | and q{new} eq $next->content() | ||||
| 342 | and $next = $next->snext_sibling() | ||||
| 343 | and $next->isa( 'PPI::Structure::List' ) | ||||
| 344 | and $next = $next->schild( 0 ) | ||||
| 345 | and $next->isa( 'PPI::Statement::Expression' ) | ||||
| 346 | and $next = $next->schild( 0 ); | ||||
| 347 | |||||
| 348 | return $self->violation( $DESC, $EXPL, $elem ); | ||||
| 349 | } | ||||
| 350 | |||||
| 351 | 1 | 9µs | 1; | ||
| 352 | |||||
| 353 | __END__ |