| Filename | /Users/timbo/perl5/perlbrew/perls/perl-5.18.2/lib/site_perl/5.18.2/Perl/Critic/Policy/Subroutines/RequireArgUnpacking.pm |
| Statements | Executed 38 statements in 1.30ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 17µs | 19µs | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::supported_parameters |
| 1 | 1 | 1 | 16µs | 16µs | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@10 |
| 1 | 1 | 1 | 16µs | 64µs | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@25 |
| 1 | 1 | 1 | 12µs | 31µs | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@16 |
| 1 | 1 | 1 | 11µs | 36µs | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@19 |
| 1 | 1 | 1 | 10µs | 11µs | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::default_severity |
| 1 | 1 | 1 | 8µs | 19µs | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@11 |
| 1 | 1 | 1 | 8µs | 426µs | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@22 |
| 1 | 1 | 1 | 8µs | 42µs | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@14 |
| 1 | 1 | 1 | 8µs | 11µs | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@12 |
| 1 | 1 | 1 | 7µs | 377µs | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@15 |
| 1 | 1 | 1 | 7µs | 187µs | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@20 |
| 1 | 1 | 1 | 5µs | 5µs | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@18 |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::_get_arg_symbols |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::_is_cast_of_array |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::_is_cast_of_scalar |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::_is_delegation |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::_is_postfix_foreach |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::_is_size_check |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::_is_unpack |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::_legal_after_size_check |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::_legal_before_size_check |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::_magic_finder |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::applies_to |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::default_themes |
| 0 | 0 | 0 | 0s | 0s | Perl::Critic::Policy::Subroutines::RequireArgUnpacking::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::Subroutines::RequireArgUnpacking; | ||||
| 9 | |||||
| 10 | 2 | 40µs | 1 | 16µs | # spent 16µs within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::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::Subroutines::RequireArgUnpacking::BEGIN@10 |
| 11 | 2 | 20µs | 2 | 31µs | # spent 19µs (8+11) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@11 which was called:
# once (8µs+11µs) by Module::Pluggable::Object::_require at line 11 # spent 19µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@11
# spent 11µs making 1 call to strict::import |
| 12 | 2 | 18µs | 2 | 15µs | # spent 11µs (8+4) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@12 which was called:
# once (8µs+4µs) by Module::Pluggable::Object::_require at line 12 # spent 11µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@12
# spent 4µs making 1 call to warnings::import |
| 13 | |||||
| 14 | 2 | 22µs | 2 | 75µs | # spent 42µs (8+34) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@14 which was called:
# once (8µs+34µs) by Module::Pluggable::Object::_require at line 14 # spent 42µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@14
# spent 34µs making 1 call to Exporter::import |
| 15 | 2 | 22µs | 2 | 747µs | # spent 377µs (7+370) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@15 which was called:
# once (7µs+370µs) by Module::Pluggable::Object::_require at line 15 # spent 377µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@15
# spent 370µs making 1 call to English::import |
| 16 | 2 | 21µs | 2 | 50µs | # spent 31µs (12+19) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@16 which was called:
# once (12µs+19µs) by Module::Pluggable::Object::_require at line 16 # spent 31µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@16
# spent 19µs making 1 call to Exporter::import |
| 17 | |||||
| 18 | 2 | 20µs | 1 | 5µs | # spent 5µs within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@18 which was called:
# once (5µs+0s) by Module::Pluggable::Object::_require at line 18 # spent 5µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@18 |
| 19 | 2 | 22µs | 2 | 43µs | # spent 36µs (11+25) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@19 which was called:
# once (11µs+25µs) by Module::Pluggable::Object::_require at line 19 # spent 36µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@19
# spent 8µs making 1 call to List::Util::import |
| 20 | 2 | 26µs | 2 | 366µs | # spent 187µs (7+179) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@20 which was called:
# once (7µs+179µs) by Module::Pluggable::Object::_require at line 20 # spent 187µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@20
# spent 179µs making 1 call to Exporter::Tiny::import |
| 21 | |||||
| 22 | 1 | 200ns | # spent 426µs (8+419) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@22 which was called:
# once (8µs+419µs) by Module::Pluggable::Object::_require at line 24 | ||
| 23 | :booleans :characters hashify :severities words_from_string | ||||
| 24 | 1 | 33µs | 2 | 845µs | >; # spent 426µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@22
# spent 418µs making 1 call to Exporter::import |
| 25 | 2 | 1.01ms | 2 | 112µs | # spent 64µs (16+48) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@25 which was called:
# once (16µs+48µs) by Module::Pluggable::Object::_require at line 25 # spent 64µs making 1 call to Perl::Critic::Policy::Subroutines::RequireArgUnpacking::BEGIN@25
# spent 48µs making 1 call to base::import |
| 26 | |||||
| 27 | 1 | 600ns | our $VERSION = '1.121'; | ||
| 28 | |||||
| 29 | #----------------------------------------------------------------------------- | ||||
| 30 | |||||
| 31 | 1 | 2µs | 1 | 30µs | Readonly::Scalar my $AT => q{@}; # spent 30µs making 1 call to Readonly::Scalar |
| 32 | 1 | 1µs | 1 | 21µs | Readonly::Scalar my $AT_ARG => q{@_}; ## no critic (InterpolationOfMetachars) # spent 21µs making 1 call to Readonly::Scalar |
| 33 | 1 | 900ns | 1 | 20µs | Readonly::Scalar my $DOLLAR => q{$}; # spent 20µs making 1 call to Readonly::Scalar |
| 34 | 1 | 900ns | 1 | 19µs | Readonly::Scalar my $DOLLAR_ARG => q{$_}; ## no critic (InterpolationOfMetaChars) # spent 19µs making 1 call to Readonly::Scalar |
| 35 | |||||
| 36 | 1 | 4µs | 2 | 21µs | Readonly::Scalar my $DESC => qq{Always unpack $AT_ARG first}; # spent 20µs making 1 call to Readonly::Scalar
# spent 2µs making 1 call to Readonly::Scalar::FETCH |
| 37 | 1 | 2µs | 1 | 40µs | Readonly::Scalar my $EXPL => [178]; # spent 40µs making 1 call to Readonly::Scalar |
| 38 | |||||
| 39 | #----------------------------------------------------------------------------- | ||||
| 40 | |||||
| 41 | # spent 19µs (17+2) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::supported_parameters which was called:
# once (17µs+2µs) by Perl::Critic::Policy::new at line 88 of Perl/Critic/Policy.pm | ||||
| 42 | return ( | ||||
| 43 | { | ||||
| 44 | 1 | 15µs | 2 | 2µs | name => 'short_subroutine_statements', # spent 2µs making 2 calls to Readonly::Scalar::FETCH, avg 1µs/call |
| 45 | description => | ||||
| 46 | 'The number of statements to allow without unpacking.', | ||||
| 47 | default_string => '0', | ||||
| 48 | behavior => 'integer', | ||||
| 49 | integer_minimum => 0, | ||||
| 50 | }, | ||||
| 51 | { | ||||
| 52 | name => 'allow_subscripts', | ||||
| 53 | description => | ||||
| 54 | 'Should unpacking from array slices and elements be allowed?', | ||||
| 55 | default_string => $FALSE, | ||||
| 56 | behavior => 'boolean', | ||||
| 57 | }, | ||||
| 58 | { | ||||
| 59 | name => 'allow_delegation_to', | ||||
| 60 | description => | ||||
| 61 | 'Allow the usual delegation idiom to these namespaces/subroutines', | ||||
| 62 | behavior => 'string list', | ||||
| 63 | list_always_present_values => [ qw< SUPER:: NEXT:: > ], | ||||
| 64 | } | ||||
| 65 | ); | ||||
| 66 | } | ||||
| 67 | |||||
| 68 | 1 | 2µs | # spent 11µs (10+1) within Perl::Critic::Policy::Subroutines::RequireArgUnpacking::default_severity which was called:
# once (10µs+1µs) by Perl::Critic::Policy::get_severity at line 331 of Perl/Critic/Policy.pm | ||
| 69 | sub default_themes { return qw( core pbp maintenance ) } | ||||
| 70 | sub applies_to { return 'PPI::Statement::Sub' } | ||||
| 71 | |||||
| 72 | #----------------------------------------------------------------------------- | ||||
| 73 | |||||
| 74 | sub violates { | ||||
| 75 | my ( $self, $elem, undef ) = @_; | ||||
| 76 | |||||
| 77 | # forward declaration? | ||||
| 78 | return if not $elem->block; | ||||
| 79 | |||||
| 80 | my @statements = $elem->block->schildren; | ||||
| 81 | |||||
| 82 | # empty sub? | ||||
| 83 | return if not @statements; | ||||
| 84 | |||||
| 85 | # Don't apply policy to short subroutines | ||||
| 86 | |||||
| 87 | # Should we instead be doing a find() for PPI::Statement | ||||
| 88 | # instances? That is, should we count all statements instead of | ||||
| 89 | # just top-level statements? | ||||
| 90 | return if $self->{_short_subroutine_statements} >= @statements; | ||||
| 91 | |||||
| 92 | # look for explicit dereferences of @_, including '$_[0]' | ||||
| 93 | # You may use "... = @_;" in the first paragraph of the sub | ||||
| 94 | # Don't descend into nested or anonymous subs | ||||
| 95 | my $state = 'unpacking'; # still in unpacking paragraph | ||||
| 96 | for my $statement (@statements) { | ||||
| 97 | |||||
| 98 | my @magic = _get_arg_symbols($statement); | ||||
| 99 | |||||
| 100 | my $saw_unpack = $FALSE; | ||||
| 101 | |||||
| 102 | MAGIC: | ||||
| 103 | for my $magic (@magic) { | ||||
| 104 | # allow conditional checks on the size of @_ | ||||
| 105 | next MAGIC if _is_size_check($magic); | ||||
| 106 | |||||
| 107 | if ('unpacking' eq $state) { | ||||
| 108 | if ($self->_is_unpack($magic)) { | ||||
| 109 | $saw_unpack = $TRUE; | ||||
| 110 | next MAGIC; | ||||
| 111 | } | ||||
| 112 | } | ||||
| 113 | |||||
| 114 | # allow @$_[] construct in "... for ();" | ||||
| 115 | # Check for "print @$_[] for ()" construct (rt39601) | ||||
| 116 | next MAGIC | ||||
| 117 | if _is_cast_of_array($magic) and _is_postfix_foreach($magic); | ||||
| 118 | |||||
| 119 | # allow $$_[], which is equivalent to $_->[] and not a use | ||||
| 120 | # of @_ at all. | ||||
| 121 | next MAGIC | ||||
| 122 | if _is_cast_of_scalar( $magic ); | ||||
| 123 | |||||
| 124 | # allow delegation of the form "$self->SUPER::foo( @_ );" | ||||
| 125 | next MAGIC | ||||
| 126 | if $self->_is_delegation( $magic ); | ||||
| 127 | |||||
| 128 | # If we make it this far, it is a violation | ||||
| 129 | return $self->violation( $DESC, $EXPL, $elem ); | ||||
| 130 | } | ||||
| 131 | if (not $saw_unpack) { | ||||
| 132 | $state = 'post_unpacking'; | ||||
| 133 | } | ||||
| 134 | } | ||||
| 135 | return; # OK | ||||
| 136 | } | ||||
| 137 | |||||
| 138 | sub _is_unpack { | ||||
| 139 | my ($self, $magic) = @_; | ||||
| 140 | |||||
| 141 | my $prev = $magic->sprevious_sibling(); | ||||
| 142 | my $next = $magic->snext_sibling(); | ||||
| 143 | |||||
| 144 | # If we have a subscript, we're dealing with an array slice on @_ | ||||
| 145 | # or an array element of @_. See RT #34009. | ||||
| 146 | if ( $next and $next->isa('PPI::Structure::Subscript') ) { | ||||
| 147 | $self->{_allow_subscripts} or return; | ||||
| 148 | $next = $next->snext_sibling; | ||||
| 149 | } | ||||
| 150 | |||||
| 151 | return $TRUE if | ||||
| 152 | $prev | ||||
| 153 | and $prev->isa('PPI::Token::Operator') | ||||
| 154 | and q{=} eq $prev->content() | ||||
| 155 | and ( | ||||
| 156 | not $next | ||||
| 157 | or $next->isa('PPI::Token::Structure') | ||||
| 158 | and $SCOLON eq $next->content() | ||||
| 159 | ); | ||||
| 160 | return; | ||||
| 161 | } | ||||
| 162 | |||||
| 163 | sub _is_size_check { | ||||
| 164 | my ($magic) = @_; | ||||
| 165 | |||||
| 166 | # No size check on $_[0]. RT #34009. | ||||
| 167 | $AT eq $magic->raw_type or return; | ||||
| 168 | |||||
| 169 | my $prev = $magic->sprevious_sibling; | ||||
| 170 | my $next = $magic->snext_sibling; | ||||
| 171 | |||||
| 172 | if ( $prev || $next ) { | ||||
| 173 | |||||
| 174 | return $TRUE | ||||
| 175 | if _legal_before_size_check( $prev ) | ||||
| 176 | and _legal_after_size_check( $next ); | ||||
| 177 | } | ||||
| 178 | |||||
| 179 | my $parent = $magic; | ||||
| 180 | { | ||||
| 181 | $parent = $parent->parent() | ||||
| 182 | or return; | ||||
| 183 | $prev = $parent->sprevious_sibling(); | ||||
| 184 | $next = $parent->snext_sibling(); | ||||
| 185 | $prev | ||||
| 186 | or $next | ||||
| 187 | or redo; | ||||
| 188 | } # until ( $prev || $next ); | ||||
| 189 | |||||
| 190 | return $TRUE | ||||
| 191 | if $parent->isa( 'PPI::Structure::Condition' ); | ||||
| 192 | |||||
| 193 | return; | ||||
| 194 | } | ||||
| 195 | |||||
| 196 | { | ||||
| 197 | |||||
| 198 | 2 | 4µs | 2 | 35µs | Readonly::Hash my %LEGAL_NEXT_OPER => hashify( # spent 31µs making 1 call to Readonly::Hash
# spent 4µs making 1 call to Perl::Critic::Utils::hashify |
| 199 | qw{ && || == != > >= < <= and or } ); | ||||
| 200 | |||||
| 201 | 1 | 2µs | 2 | 20µs | Readonly::Hash my %LEGAL_NEXT_STRUCT => hashify( qw{ ; } ); # spent 18µs making 1 call to Readonly::Hash
# spent 2µs making 1 call to Perl::Critic::Utils::hashify |
| 202 | |||||
| 203 | sub _legal_after_size_check { | ||||
| 204 | my ( $next ) = @_; | ||||
| 205 | |||||
| 206 | $next | ||||
| 207 | or return $TRUE; | ||||
| 208 | |||||
| 209 | $next->isa( 'PPI::Token::Operator' ) | ||||
| 210 | and return $LEGAL_NEXT_OPER{ $next->content() }; | ||||
| 211 | |||||
| 212 | $next->isa( 'PPI::Token::Structure' ) | ||||
| 213 | and return $LEGAL_NEXT_STRUCT{ $next->content() }; | ||||
| 214 | |||||
| 215 | return; | ||||
| 216 | } | ||||
| 217 | } | ||||
| 218 | |||||
| 219 | { | ||||
| 220 | |||||
| 221 | 2 | 3µs | 2 | 32µs | Readonly::Hash my %LEGAL_PREV_OPER => hashify( # spent 28µs making 1 call to Readonly::Hash
# spent 4µs making 1 call to Perl::Critic::Utils::hashify |
| 222 | qw{ && || ! == != > >= < <= and or not } ); | ||||
| 223 | |||||
| 224 | 1 | 2µs | 2 | 22µs | Readonly::Hash my %LEGAL_PREV_WORD => hashify( # spent 20µs making 1 call to Readonly::Hash
# spent 2µs making 1 call to Perl::Critic::Utils::hashify |
| 225 | qw{ if unless } ); | ||||
| 226 | |||||
| 227 | sub _legal_before_size_check { | ||||
| 228 | my ( $prev ) = @_; | ||||
| 229 | |||||
| 230 | $prev | ||||
| 231 | or return $TRUE; | ||||
| 232 | |||||
| 233 | $prev->isa( 'PPI::Token::Operator' ) | ||||
| 234 | and return $LEGAL_PREV_OPER{ $prev->content() }; | ||||
| 235 | |||||
| 236 | $prev->isa( 'PPI::Token::Word' ) | ||||
| 237 | and return $LEGAL_PREV_WORD{ $prev->content() }; | ||||
| 238 | |||||
| 239 | return; | ||||
| 240 | } | ||||
| 241 | |||||
| 242 | } | ||||
| 243 | |||||
| 244 | sub _is_postfix_foreach { | ||||
| 245 | my ($magic) = @_; | ||||
| 246 | |||||
| 247 | my $sibling = $magic; | ||||
| 248 | while ( $sibling = $sibling->snext_sibling ) { | ||||
| 249 | return $TRUE | ||||
| 250 | if | ||||
| 251 | $sibling->isa('PPI::Token::Word') | ||||
| 252 | and $sibling =~ m< \A for (?:each)? \z >xms; | ||||
| 253 | } | ||||
| 254 | return; | ||||
| 255 | } | ||||
| 256 | |||||
| 257 | sub _is_cast_of_array { | ||||
| 258 | my ($magic) = @_; | ||||
| 259 | |||||
| 260 | my $prev = $magic->sprevious_sibling; | ||||
| 261 | |||||
| 262 | return $TRUE | ||||
| 263 | if ( $prev && $prev->content() eq $AT ) | ||||
| 264 | and $prev->isa('PPI::Token::Cast'); | ||||
| 265 | return; | ||||
| 266 | } | ||||
| 267 | |||||
| 268 | # This subroutine recognizes (e.g.) $$_[0]. This is a use of $_ (equivalent to | ||||
| 269 | # $_->[0]), not @_. | ||||
| 270 | |||||
| 271 | sub _is_cast_of_scalar { | ||||
| 272 | my ($magic) = @_; | ||||
| 273 | |||||
| 274 | my $prev = $magic->sprevious_sibling; | ||||
| 275 | my $next = $magic->snext_sibling; | ||||
| 276 | |||||
| 277 | return $DOLLAR_ARG eq $magic->content() && | ||||
| 278 | $prev && $prev->isa('PPI::Token::Cast') && | ||||
| 279 | $DOLLAR eq $prev->content() && | ||||
| 280 | $next && $next->isa('PPI::Structure::Subscript'); | ||||
| 281 | } | ||||
| 282 | |||||
| 283 | # A literal @_ is allowed as the argument for a delegation. | ||||
| 284 | # An example of the idiom we are looking for is $self->SUPER::foo(@_). | ||||
| 285 | # The argument list of (@_) is required; no other use of @_ is allowed. | ||||
| 286 | |||||
| 287 | sub _is_delegation { | ||||
| 288 | my ($self, $magic) = @_; | ||||
| 289 | |||||
| 290 | $AT_ARG eq $magic->content() or return; # Not a literal '@_'. | ||||
| 291 | my $parent = $magic->parent() # Don't know what to do with | ||||
| 292 | or return; # orphans. | ||||
| 293 | $parent->isa( 'PPI::Statement::Expression' ) | ||||
| 294 | or return; # Parent must be expression. | ||||
| 295 | 1 == $parent->schildren() # '@_' must stand alone in | ||||
| 296 | or return; # its expression. | ||||
| 297 | $parent = $parent->parent() # Still don't know what to do | ||||
| 298 | or return; # with orphans. | ||||
| 299 | $parent->isa ( 'PPI::Structure::List' ) | ||||
| 300 | or return; # Parent must be a list. | ||||
| 301 | 1 == $parent->schildren() # '@_' must stand alone in | ||||
| 302 | or return; # the argument list. | ||||
| 303 | my $subroutine_name = $parent->sprevious_sibling() | ||||
| 304 | or return; # Missing sub name. | ||||
| 305 | $subroutine_name->isa( 'PPI::Token::Word' ) | ||||
| 306 | or return; | ||||
| 307 | $self->{_allow_delegation_to}{$subroutine_name} | ||||
| 308 | and return 1; | ||||
| 309 | my ($subroutine_namespace) = $subroutine_name =~ m/ \A ( .* ::) \w+ \z /smx | ||||
| 310 | or return; | ||||
| 311 | return $self->{_allow_delegation_to}{$subroutine_namespace}; | ||||
| 312 | } | ||||
| 313 | |||||
| 314 | |||||
| 315 | sub _get_arg_symbols { | ||||
| 316 | my ($statement) = @_; | ||||
| 317 | |||||
| 318 | return grep {$AT_ARG eq $_->symbol} @{$statement->find(\&_magic_finder) || []}; | ||||
| 319 | } | ||||
| 320 | |||||
| 321 | sub _magic_finder { | ||||
| 322 | # Find all @_ and $_[\d+] not inside of nested subs | ||||
| 323 | my (undef, $elem) = @_; | ||||
| 324 | return $TRUE if $elem->isa('PPI::Token::Magic'); # match | ||||
| 325 | |||||
| 326 | if ($elem->isa('PPI::Structure::Block')) { | ||||
| 327 | # don't descend into a nested named sub | ||||
| 328 | return if $elem->statement->isa('PPI::Statement::Sub'); | ||||
| 329 | |||||
| 330 | my $prev = $elem->sprevious_sibling; | ||||
| 331 | # don't descend into a nested anon sub block | ||||
| 332 | return if $prev | ||||
| 333 | and $prev->isa('PPI::Token::Word') | ||||
| 334 | and 'sub' eq $prev->content(); | ||||
| 335 | } | ||||
| 336 | |||||
| 337 | return $FALSE; # no match, descend | ||||
| 338 | } | ||||
| 339 | |||||
| 340 | |||||
| 341 | 1 | 9µs | 1; | ||
| 342 | |||||
| 343 | __END__ |