| Filename | /Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/Perl/Critic/Policy/ErrorHandling/RequireCarping.pm |
| Statements | Executed 22 statements in 1.21ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 17µs | 81µs | Perl::Critic::Policy::ErrorHandling::RequireCarping::BEGIN@19 |
| 1 | 1 | 1 | 16µs | 16µs | Perl::Critic::Policy::ErrorHandling::RequireCarping::BEGIN@10 |
| 1 | 1 | 1 | 10µs | 31µs | Perl::Critic::Policy::ErrorHandling::RequireCarping::BEGIN@18 |
| 1 | 1 | 1 | 9µs | 12µs | Perl::Critic::Policy::ErrorHandling::RequireCarping::default_severity |
| 1 | 1 | 1 | 9µs | 9µs | Perl::Critic::Policy::ErrorHandling::RequireCarping::supported_parameters |
| 1 | 1 | 1 | 7µs | 666µs | Perl::Critic::Policy::ErrorHandling::RequireCarping::BEGIN@15 |
| 1 | 1 | 1 | 7µs | 18µs | Perl::Critic::Policy::ErrorHandling::RequireCarping::BEGIN@11 |
| 1 | 1 | 1 | 7µs | 10µs | Perl::Critic::Policy::ErrorHandling::RequireCarping::BEGIN@12 |
| 1 | 1 | 1 | 7µs | 27µs | Perl::Critic::Policy::ErrorHandling::RequireCarping::BEGIN@13 |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ErrorHandling::RequireCarping::_determine_if_list_is_a_plain_list_and_get_last_child |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ErrorHandling::RequireCarping::_find_last_element_in_subexpression |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ErrorHandling::RequireCarping::_find_last_flattened_argument_list_element |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ErrorHandling::RequireCarping::_is_complex_expression_token |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ErrorHandling::RequireCarping::_is_element_contained_in_subroutine |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ErrorHandling::RequireCarping::_is_element_in_namespace_main |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ErrorHandling::RequireCarping::_is_postfix_operator |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ErrorHandling::RequireCarping::_is_simple_list_element_token |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ErrorHandling::RequireCarping::_last_flattened_argument_list_element_ends_in_newline |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ErrorHandling::RequireCarping::applies_to |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ErrorHandling::RequireCarping::default_themes |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::ErrorHandling::RequireCarping::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::ErrorHandling::RequireCarping; | ||||
| 9 | |||||
| 10 | 2 | 42µs | 1 | 16µs | # spent 16µs within Perl::Critic::Policy::ErrorHandling::RequireCarping::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::ErrorHandling::RequireCarping::BEGIN@10 |
| 11 | 2 | 19µs | 2 | 29µs | # spent 18µs (7+11) within Perl::Critic::Policy::ErrorHandling::RequireCarping::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::ErrorHandling::RequireCarping::BEGIN@11
# spent 11µs making 1 call to strict::import |
| 12 | 2 | 17µs | 2 | 14µs | # spent 10µs (7+4) within Perl::Critic::Policy::ErrorHandling::RequireCarping::BEGIN@12 which was called:
# once (7µs+4µs) by Module::Pluggable::Object::_require at line 12 # spent 10µs making 1 call to Perl::Critic::Policy::ErrorHandling::RequireCarping::BEGIN@12
# spent 4µs making 1 call to warnings::import |
| 13 | 2 | 24µs | 2 | 47µs | # spent 27µs (7+20) within Perl::Critic::Policy::ErrorHandling::RequireCarping::BEGIN@13 which was called:
# once (7µs+20µs) by Module::Pluggable::Object::_require at line 13 # spent 27µs making 1 call to Perl::Critic::Policy::ErrorHandling::RequireCarping::BEGIN@13
# spent 20µs making 1 call to Exporter::import |
| 14 | |||||
| 15 | 1 | 200ns | # spent 666µs (7+659) within Perl::Critic::Policy::ErrorHandling::RequireCarping::BEGIN@15 which was called:
# once (7µs+659µs) by Module::Pluggable::Object::_require at line 17 | ||
| 16 | :booleans :characters :severities :classification :data_conversion | ||||
| 17 | 1 | 25µs | 2 | 1.32ms | }; # spent 666µs making 1 call to Perl::Critic::Policy::ErrorHandling::RequireCarping::BEGIN@15
# spent 659µs making 1 call to Exporter::import |
| 18 | 2 | 23µs | 2 | 52µs | # spent 31µs (10+22) within Perl::Critic::Policy::ErrorHandling::RequireCarping::BEGIN@18 which was called:
# once (10µs+22µs) by Module::Pluggable::Object::_require at line 18 # spent 31µs making 1 call to Perl::Critic::Policy::ErrorHandling::RequireCarping::BEGIN@18
# spent 22µs making 1 call to Exporter::import |
| 19 | 2 | 1.02ms | 2 | 146µs | # spent 81µs (17+64) within Perl::Critic::Policy::ErrorHandling::RequireCarping::BEGIN@19 which was called:
# once (17µs+64µs) by Module::Pluggable::Object::_require at line 19 # spent 81µs making 1 call to Perl::Critic::Policy::ErrorHandling::RequireCarping::BEGIN@19
# spent 64µs making 1 call to base::import |
| 20 | |||||
| 21 | 1 | 800ns | our $VERSION = '1.121'; | ||
| 22 | |||||
| 23 | #----------------------------------------------------------------------------- | ||||
| 24 | |||||
| 25 | 1 | 4µs | 1 | 66µs | Readonly::Scalar my $EXPL => [ 283 ]; # spent 66µs making 1 call to Readonly::Scalar |
| 26 | |||||
| 27 | #----------------------------------------------------------------------------- | ||||
| 28 | |||||
| 29 | # spent 9µs within Perl::Critic::Policy::ErrorHandling::RequireCarping::supported_parameters which was called:
# once (9µs+0s) by Perl::Critic::Policy::new at line 88 of Perl/Critic/Policy.pm | ||||
| 30 | return ( | ||||
| 31 | { | ||||
| 32 | 1 | 12µs | name => 'allow_messages_ending_with_newlines', | ||
| 33 | description => q{Don't complain about die or warn if the message ends in a newline.}, | ||||
| 34 | default_string => '1', | ||||
| 35 | behavior => 'boolean', | ||||
| 36 | }, | ||||
| 37 | { | ||||
| 38 | name => 'allow_in_main_unless_in_subroutine', | ||||
| 39 | description => q{Don't complain about die or warn in main::, unless in a subroutine.}, | ||||
| 40 | default_string => '0', | ||||
| 41 | behavior => 'boolean', | ||||
| 42 | }, | ||||
| 43 | ); | ||||
| 44 | } | ||||
| 45 | |||||
| 46 | 1 | 2µs | # spent 12µs (9+2) within Perl::Critic::Policy::ErrorHandling::RequireCarping::default_severity which was called:
# once (9µs+2µs) by Perl::Critic::Policy::get_severity at line 331 of Perl/Critic/Policy.pm | ||
| 47 | sub default_themes { return qw( core pbp maintenance certrule ) } | ||||
| 48 | sub applies_to { return 'PPI::Token::Word' } | ||||
| 49 | |||||
| 50 | #----------------------------------------------------------------------------- | ||||
| 51 | |||||
| 52 | sub violates { | ||||
| 53 | my ( $self, $elem, undef ) = @_; | ||||
| 54 | |||||
| 55 | my $alternative; | ||||
| 56 | if ( $elem eq 'warn' ) { | ||||
| 57 | $alternative = 'carp'; | ||||
| 58 | } | ||||
| 59 | elsif ( $elem eq 'die' ) { | ||||
| 60 | $alternative = 'croak'; | ||||
| 61 | } | ||||
| 62 | else { | ||||
| 63 | return; | ||||
| 64 | } | ||||
| 65 | |||||
| 66 | return if ! is_function_call($elem); | ||||
| 67 | |||||
| 68 | if ($self->{_allow_messages_ending_with_newlines}) { | ||||
| 69 | return if _last_flattened_argument_list_element_ends_in_newline($elem); | ||||
| 70 | } | ||||
| 71 | |||||
| 72 | return if $self->{_allow_in_main_unless_in_subroutine} | ||||
| 73 | && !$self->_is_element_contained_in_subroutine( $elem ) | ||||
| 74 | && $self->_is_element_in_namespace_main( $elem ); # RT #56619 | ||||
| 75 | |||||
| 76 | my $desc = qq{"$elem" used instead of "$alternative"}; | ||||
| 77 | return $self->violation( $desc, $EXPL, $elem ); | ||||
| 78 | } | ||||
| 79 | |||||
| 80 | #----------------------------------------------------------------------------- | ||||
| 81 | |||||
| 82 | sub _last_flattened_argument_list_element_ends_in_newline { | ||||
| 83 | my $die_or_warn = shift; | ||||
| 84 | |||||
| 85 | my $last_flattened_argument = | ||||
| 86 | _find_last_flattened_argument_list_element($die_or_warn) | ||||
| 87 | or return $FALSE; | ||||
| 88 | |||||
| 89 | if ( $last_flattened_argument->isa('PPI::Token::Quote') ) { | ||||
| 90 | my $last_flattened_argument_string = | ||||
| 91 | $last_flattened_argument->string(); | ||||
| 92 | if ( | ||||
| 93 | $last_flattened_argument_string =~ m{ \n \z }xms | ||||
| 94 | or ( | ||||
| 95 | ( | ||||
| 96 | $last_flattened_argument->isa('PPI::Token::Quote::Double') | ||||
| 97 | or $last_flattened_argument->isa('PPI::Token::Quote::Interpolate') | ||||
| 98 | ) | ||||
| 99 | and $last_flattened_argument_string =~ m{ [\\] n \z }xms | ||||
| 100 | ) | ||||
| 101 | ) { | ||||
| 102 | return $TRUE; | ||||
| 103 | } | ||||
| 104 | } | ||||
| 105 | elsif ( $last_flattened_argument->isa('PPI::Token::HereDoc') ) { | ||||
| 106 | return $TRUE; | ||||
| 107 | } | ||||
| 108 | |||||
| 109 | return $FALSE | ||||
| 110 | } | ||||
| 111 | |||||
| 112 | #----------------------------------------------------------------------------- | ||||
| 113 | # Here starts the fun. Explanation by example: | ||||
| 114 | # | ||||
| 115 | # Let's say we've got the following (contrived) statement: | ||||
| 116 | # | ||||
| 117 | # die q{Isn't }, ( $this, ( " fun?\n" ) , ) if "It isn't Monday."; | ||||
| 118 | # | ||||
| 119 | # This statement should pass because the last parameter that die is going to | ||||
| 120 | # get is C<" fun?\n">. | ||||
| 121 | # | ||||
| 122 | # The approach is to first find the last non-flattened parameter. If this | ||||
| 123 | # is a simple token, we're done. Else, it's some aggregate thing. We can't | ||||
| 124 | # tell what C<some_function( "foo\n" )> is going to do, so we give up on | ||||
| 125 | # anything other than a PPI::Structure::List. | ||||
| 126 | # | ||||
| 127 | # There are three possible scenarios for the children of a List: | ||||
| 128 | # | ||||
| 129 | # * No children of the List, i.e. the list looks like C< ( ) >. | ||||
| 130 | # * One PPI::Statement::Expression element. | ||||
| 131 | # * One PPI::Statement element. That's right, an instance of the base | ||||
| 132 | # statement class and not some subclass. *sigh* | ||||
| 133 | # | ||||
| 134 | # In the first case, we're done. The latter two cases get treated | ||||
| 135 | # identically. We get the last child of the Statement and start the search | ||||
| 136 | # all over again. | ||||
| 137 | # | ||||
| 138 | # Back to our example. The PPI tree for this expression is | ||||
| 139 | # | ||||
| 140 | # PPI::Document | ||||
| 141 | # PPI::Statement | ||||
| 142 | # PPI::Token::Word 'die' | ||||
| 143 | # PPI::Token::Quote::Literal 'q{Isn't }' | ||||
| 144 | # PPI::Token::Operator ',' | ||||
| 145 | # PPI::Structure::List ( ... ) | ||||
| 146 | # PPI::Statement::Expression | ||||
| 147 | # PPI::Token::Symbol '$this' | ||||
| 148 | # PPI::Token::Operator ',' | ||||
| 149 | # PPI::Structure::List ( ... ) | ||||
| 150 | # PPI::Statement::Expression | ||||
| 151 | # PPI::Token::Quote::Double '" fun?\n"' | ||||
| 152 | # PPI::Token::Operator ',' | ||||
| 153 | # PPI::Token::Word 'if' | ||||
| 154 | # PPI::Token::Quote::Double '"It isn't Monday.\n"' | ||||
| 155 | # PPI::Token::Structure ';' | ||||
| 156 | # | ||||
| 157 | # We're starting with the Word containing 'die' (it could just as well be | ||||
| 158 | # 'warn') because the earlier parts of validate() have taken care of any | ||||
| 159 | # other possibility. We're going to scan forward through 'die's siblings | ||||
| 160 | # until we reach what we think the end of its parameters are. So we get | ||||
| 161 | # | ||||
| 162 | # 1. A Literal. A perfectly good argument. | ||||
| 163 | # 2. A comma operator. Looks like we've got more to go. | ||||
| 164 | # 3. A List. Another argument. | ||||
| 165 | # 4. The Word 'if'. Oops. That's a postfix operator. | ||||
| 166 | # | ||||
| 167 | # Thus, the last parameter is the List. So, we've got to scan backwards | ||||
| 168 | # through the components of the List; again, the goal is to find the last | ||||
| 169 | # value in the flattened list. | ||||
| 170 | # | ||||
| 171 | # Before decending into the List, we check that it isn't a subroutine call by | ||||
| 172 | # looking at its prior sibling. In this case, the prior sibling is a comma | ||||
| 173 | # operator, so it's fine. | ||||
| 174 | # | ||||
| 175 | # The List has one Expression element as we expect. We grab the Expression's | ||||
| 176 | # last child and start all over again. | ||||
| 177 | # | ||||
| 178 | # 1. The last child is a comma operator, which Perl will ignore, so we | ||||
| 179 | # skip it. | ||||
| 180 | # 2. The comma's prior sibling is a List. This is the last significant | ||||
| 181 | # part of the outer list. | ||||
| 182 | # 3. The List's prior sibling isn't a Word, so we can continue because the | ||||
| 183 | # List is not a parameter list. | ||||
| 184 | # 4. We go through the child Expression and find that the last child of | ||||
| 185 | # that is a PPI::Token::Quote::Double, which is a simple, non-compound | ||||
| 186 | # token. We return that and we're done. | ||||
| 187 | |||||
| 188 | sub _find_last_flattened_argument_list_element { | ||||
| 189 | my $die_or_warn = shift; | ||||
| 190 | |||||
| 191 | # Zoom forward... | ||||
| 192 | my $current_candidate = | ||||
| 193 | _find_last_element_in_subexpression($die_or_warn); | ||||
| 194 | |||||
| 195 | # ... scan back. | ||||
| 196 | while ( | ||||
| 197 | $current_candidate | ||||
| 198 | and not _is_simple_list_element_token( $current_candidate ) | ||||
| 199 | and not _is_complex_expression_token( $current_candidate ) | ||||
| 200 | ) { | ||||
| 201 | if ( $current_candidate->isa('PPI::Structure::List') ) { | ||||
| 202 | $current_candidate = | ||||
| 203 | _determine_if_list_is_a_plain_list_and_get_last_child( | ||||
| 204 | $current_candidate, | ||||
| 205 | $die_or_warn | ||||
| 206 | ); | ||||
| 207 | } elsif ( not $current_candidate->isa('PPI::Token') ) { | ||||
| 208 | return; | ||||
| 209 | } else { | ||||
| 210 | $current_candidate = $current_candidate->sprevious_sibling(); | ||||
| 211 | } | ||||
| 212 | } | ||||
| 213 | |||||
| 214 | return if not $current_candidate; | ||||
| 215 | return if _is_complex_expression_token( $current_candidate ); | ||||
| 216 | |||||
| 217 | my $penultimate_element = $current_candidate->sprevious_sibling(); | ||||
| 218 | if ($penultimate_element) { | ||||
| 219 | # Bail if we've got a Word in front of the Element that isn't | ||||
| 220 | # the original 'die' or 'warn' or anything else that isn't | ||||
| 221 | # a comma or dot operator. | ||||
| 222 | if ( $penultimate_element->isa('PPI::Token::Operator') ) { | ||||
| 223 | if ( | ||||
| 224 | $penultimate_element ne $COMMA | ||||
| 225 | and $penultimate_element ne $PERIOD | ||||
| 226 | ) { | ||||
| 227 | return; | ||||
| 228 | } | ||||
| 229 | } elsif ( $penultimate_element != $die_or_warn ) { | ||||
| 230 | return | ||||
| 231 | } | ||||
| 232 | } | ||||
| 233 | |||||
| 234 | return $current_candidate; | ||||
| 235 | } | ||||
| 236 | |||||
| 237 | #----------------------------------------------------------------------------- | ||||
| 238 | # This is the part where we scan forward from the 'die' or 'warn' to find | ||||
| 239 | # the last argument. | ||||
| 240 | |||||
| 241 | sub _find_last_element_in_subexpression { | ||||
| 242 | my $die_or_warn = shift; | ||||
| 243 | |||||
| 244 | my $last_following_sibling; | ||||
| 245 | my $next_sibling = $die_or_warn; | ||||
| 246 | while ( | ||||
| 247 | $next_sibling = $next_sibling->snext_sibling() | ||||
| 248 | and not _is_postfix_operator( $next_sibling ) | ||||
| 249 | ) { | ||||
| 250 | $last_following_sibling = $next_sibling; | ||||
| 251 | } | ||||
| 252 | |||||
| 253 | return $last_following_sibling; | ||||
| 254 | } | ||||
| 255 | |||||
| 256 | #----------------------------------------------------------------------------- | ||||
| 257 | # Ensure that the list isn't a parameter list. Find the last element of it. | ||||
| 258 | |||||
| 259 | sub _determine_if_list_is_a_plain_list_and_get_last_child { | ||||
| 260 | my ($list, $die_or_warn) = @_; | ||||
| 261 | |||||
| 262 | my $prior_sibling = $list->sprevious_sibling(); | ||||
| 263 | |||||
| 264 | if ( $prior_sibling ) { | ||||
| 265 | # Bail if we've got a Word in front of the List that isn't | ||||
| 266 | # the original 'die' or 'warn' or anything else that isn't | ||||
| 267 | # a comma operator. | ||||
| 268 | if ( $prior_sibling->isa('PPI::Token::Operator') ) { | ||||
| 269 | if ( $prior_sibling ne $COMMA ) { | ||||
| 270 | return; | ||||
| 271 | } | ||||
| 272 | } elsif ( $prior_sibling != $die_or_warn ) { | ||||
| 273 | return | ||||
| 274 | } | ||||
| 275 | } | ||||
| 276 | |||||
| 277 | my @list_children = $list->schildren(); | ||||
| 278 | |||||
| 279 | # If zero children, nothing to look for. | ||||
| 280 | # If multiple children, then PPI is not giving us | ||||
| 281 | # anything we understand. | ||||
| 282 | return if scalar (@list_children) != 1; | ||||
| 283 | |||||
| 284 | my $list_child = $list_children[0]; | ||||
| 285 | |||||
| 286 | # If the child isn't an Expression or it is some other subclass | ||||
| 287 | # of Statement, we again don't understand PPI's output. | ||||
| 288 | return if not is_ppi_expression_or_generic_statement($list_child); | ||||
| 289 | |||||
| 290 | my @statement_children = $list_child->schildren(); | ||||
| 291 | return if scalar (@statement_children) < 1; | ||||
| 292 | |||||
| 293 | return $statement_children[-1]; | ||||
| 294 | } | ||||
| 295 | |||||
| 296 | |||||
| 297 | #----------------------------------------------------------------------------- | ||||
| 298 | 1 | 4µs | 2 | 39µs | Readonly::Hash my %POSTFIX_OPERATORS => # spent 34µs making 1 call to Readonly::Hash
# spent 4µs making 1 call to Perl::Critic::Utils::hashify |
| 299 | hashify qw{ if unless while until for foreach }; | ||||
| 300 | |||||
| 301 | sub _is_postfix_operator { | ||||
| 302 | my $element = shift; | ||||
| 303 | |||||
| 304 | if ( | ||||
| 305 | $element->isa('PPI::Token::Word') | ||||
| 306 | and $POSTFIX_OPERATORS{$element} | ||||
| 307 | ) { | ||||
| 308 | return $TRUE; | ||||
| 309 | } | ||||
| 310 | |||||
| 311 | return $FALSE; | ||||
| 312 | } | ||||
| 313 | |||||
| 314 | |||||
| 315 | 1 | 2µs | 1 | 28µs | Readonly::Array my @SIMPLE_LIST_ELEMENT_TOKEN_CLASSES => # spent 28µs making 1 call to Readonly::Array |
| 316 | qw{ | ||||
| 317 | PPI::Token::Number | ||||
| 318 | PPI::Token::Word | ||||
| 319 | PPI::Token::DashedWord | ||||
| 320 | PPI::Token::Symbol | ||||
| 321 | PPI::Token::Quote | ||||
| 322 | PPI::Token::HereDoc | ||||
| 323 | }; | ||||
| 324 | |||||
| 325 | sub _is_simple_list_element_token { | ||||
| 326 | my $element = shift; | ||||
| 327 | |||||
| 328 | return $FALSE if not $element->isa('PPI::Token'); | ||||
| 329 | |||||
| 330 | foreach my $class (@SIMPLE_LIST_ELEMENT_TOKEN_CLASSES) { | ||||
| 331 | return $TRUE if $element->isa($class); | ||||
| 332 | } | ||||
| 333 | |||||
| 334 | return $FALSE; | ||||
| 335 | } | ||||
| 336 | |||||
| 337 | |||||
| 338 | #----------------------------------------------------------------------------- | ||||
| 339 | # Tokens that can't possibly be part of an expression simple | ||||
| 340 | # enough for us to examine. | ||||
| 341 | |||||
| 342 | 1 | 2µs | 1 | 30µs | Readonly::Array my @COMPLEX_EXPRESSION_TOKEN_CLASSES => # spent 30µs making 1 call to Readonly::Array |
| 343 | qw{ | ||||
| 344 | PPI::Token::ArrayIndex | ||||
| 345 | PPI::Token::QuoteLike | ||||
| 346 | PPI::Token::Regexp | ||||
| 347 | PPI::Token::Cast | ||||
| 348 | PPI::Token::Label | ||||
| 349 | PPI::Token::Separator | ||||
| 350 | PPI::Token::Data | ||||
| 351 | PPI::Token::End | ||||
| 352 | PPI::Token::Prototype | ||||
| 353 | PPI::Token::Attribute | ||||
| 354 | PPI::Token::Unknown | ||||
| 355 | }; | ||||
| 356 | |||||
| 357 | sub _is_complex_expression_token { | ||||
| 358 | my $element = shift; | ||||
| 359 | |||||
| 360 | return $FALSE if not $element->isa('PPI::Token'); | ||||
| 361 | |||||
| 362 | foreach my $class (@COMPLEX_EXPRESSION_TOKEN_CLASSES) { | ||||
| 363 | return $TRUE if $element->isa($class); | ||||
| 364 | } | ||||
| 365 | |||||
| 366 | return $FALSE; | ||||
| 367 | } | ||||
| 368 | |||||
| 369 | #----------------------------------------------------------------------------- | ||||
| 370 | # Check whether the given element is contained in a subroutine. | ||||
| 371 | |||||
| 372 | sub _is_element_contained_in_subroutine { | ||||
| 373 | my ( $self, $elem ) = @_; | ||||
| 374 | |||||
| 375 | my $parent = $elem; | ||||
| 376 | while ( $parent = $parent->parent() ) { | ||||
| 377 | $parent->isa( 'PPI::Statement::Sub' ) and return $TRUE; | ||||
| 378 | $parent->isa( 'PPI::Structure::Block' ) or next; | ||||
| 379 | my $prior_elem = $parent->sprevious_sibling() or next; | ||||
| 380 | $prior_elem->isa( 'PPI::Token::Word' ) | ||||
| 381 | and 'sub' eq $prior_elem->content() | ||||
| 382 | and return $TRUE; | ||||
| 383 | } | ||||
| 384 | |||||
| 385 | return $FALSE; | ||||
| 386 | } | ||||
| 387 | |||||
| 388 | #----------------------------------------------------------------------------- | ||||
| 389 | # Check whether the given element is in main:: | ||||
| 390 | |||||
| 391 | sub _is_element_in_namespace_main { | ||||
| 392 | my ( $self, $elem ) = @_; | ||||
| 393 | my $current_elem = $elem; | ||||
| 394 | my $prior_elem; | ||||
| 395 | |||||
| 396 | while ( $current_elem ) { | ||||
| 397 | while ( $prior_elem = $current_elem->sprevious_sibling() ) { | ||||
| 398 | if ( $prior_elem->isa( 'PPI::Statement::Package' ) ) { | ||||
| 399 | return 'main' eq $prior_elem->namespace(); | ||||
| 400 | } | ||||
| 401 | } continue { | ||||
| 402 | $current_elem = $prior_elem; | ||||
| 403 | } | ||||
| 404 | $current_elem = $current_elem->parent(); | ||||
| 405 | } | ||||
| 406 | |||||
| 407 | return $TRUE; | ||||
| 408 | } | ||||
| 409 | |||||
| 410 | 1 | 9µs | 1; | ||
| 411 | |||||
| 412 | __END__ |