Filename | /usr/local/share/perl/5.18.2/namespace/autoclean.pm |
Statements | Executed 176 statements in 1.92ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 1.49ms | 4.06ms | BEGIN@12 | namespace::autoclean::
1 | 1 | 1 | 928µs | 1.24ms | _method_check | namespace::autoclean::
1 | 1 | 1 | 434µs | 9.34ms | BEGIN@10 | namespace::autoclean::
1 | 1 | 1 | 222µs | 2.38ms | __ANON__[:183] | namespace::autoclean::
16 | 1 | 1 | 173µs | 272µs | __ANON__[:210] | namespace::autoclean::
1 | 1 | 1 | 20µs | 38µs | import | namespace::autoclean::
1 | 1 | 1 | 17µs | 34µs | BEGIN@1 | String::Markov::
1 | 1 | 1 | 14µs | 120µs | BEGIN@11 | namespace::autoclean::
1 | 1 | 1 | 11µs | 28µs | BEGIN@203 | namespace::autoclean::
1 | 1 | 1 | 9µs | 15µs | BEGIN@2 | String::Markov::
16 | 1 | 1 | 9µs | 9µs | CORE:match (opcode) | namespace::autoclean::
0 | 0 | 0 | 0s | 0s | __ANON__[:147] | namespace::autoclean::
0 | 0 | 0 | 0s | 0s | __ANON__[:148] | namespace::autoclean::
0 | 0 | 0 | 0s | 0s | __ANON__[:149] | namespace::autoclean::
0 | 0 | 0 | 0s | 0s | __ANON__[:155] | namespace::autoclean::
0 | 0 | 0 | 0s | 0s | __ANON__[:177] | namespace::autoclean::
0 | 0 | 0 | 0s | 0s | __ANON__[:179] | namespace::autoclean::
0 | 0 | 0 | 0s | 0s | __ANON__[:194] | namespace::autoclean::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | 2 | 40µs | 2 | 51µs | # spent 34µs (17+17) within String::Markov::BEGIN@1 which was called:
# once (17µs+17µs) by String::Markov::BEGIN@9 at line 1 # spent 34µs making 1 call to String::Markov::BEGIN@1
# spent 17µs making 1 call to strict::import |
2 | 2 | 56µs | 2 | 21µs | # spent 15µs (9+6) within String::Markov::BEGIN@2 which was called:
# once (9µs+6µs) by String::Markov::BEGIN@9 at line 2 # spent 15µs making 1 call to String::Markov::BEGIN@2
# spent 6µs making 1 call to warnings::import |
3 | |||||
4 | package namespace::autoclean; # git description: 0.27-4-g47c7088 | ||||
5 | # ABSTRACT: Keep imports out of your namespace | ||||
6 | # KEYWORDS: namespaces clean dirty imports exports subroutines methods development | ||||
7 | |||||
8 | 1 | 600ns | our $VERSION = '0.28'; | ||
9 | |||||
10 | 3 | 158µs | 3 | 9.37ms | # spent 9.34ms (434µs+8.91) within namespace::autoclean::BEGIN@10 which was called:
# once (434µs+8.91ms) by String::Markov::BEGIN@9 at line 10 # spent 9.34ms making 1 call to namespace::autoclean::BEGIN@10
# spent 19µs making 1 call to Sub::Exporter::Progressive::__ANON__[Sub/Exporter/Progressive.pm:40]
# spent 11µs making 1 call to UNIVERSAL::VERSION |
11 | 2 | 37µs | 2 | 130µs | # spent 120µs (14+105) within namespace::autoclean::BEGIN@11 which was called:
# once (14µs+105µs) by String::Markov::BEGIN@9 at line 11 # spent 120µs making 1 call to namespace::autoclean::BEGIN@11
# spent 10µs making 1 call to List::Util::import |
12 | 3 | 918µs | 3 | 4.41ms | # spent 4.06ms (1.49+2.58) within namespace::autoclean::BEGIN@12 which was called:
# once (1.49ms+2.58ms) by String::Markov::BEGIN@9 at line 12 # spent 4.06ms making 1 call to namespace::autoclean::BEGIN@12
# spent 334µs making 1 call to namespace::clean::import
# spent 12µs making 1 call to UNIVERSAL::VERSION |
13 | |||||
14 | #pod =head1 SYNOPSIS | ||||
15 | #pod | ||||
16 | #pod package Foo; | ||||
17 | #pod use namespace::autoclean; | ||||
18 | #pod use Some::Package qw/imported_function/; | ||||
19 | #pod | ||||
20 | #pod sub bar { imported_function('stuff') } | ||||
21 | #pod | ||||
22 | #pod # later on: | ||||
23 | #pod Foo->bar; # works | ||||
24 | #pod Foo->imported_function; # will fail. imported_function got cleaned after compilation | ||||
25 | #pod | ||||
26 | #pod =head1 DESCRIPTION | ||||
27 | #pod | ||||
28 | #pod When you import a function into a Perl package, it will naturally also be | ||||
29 | #pod available as a method. | ||||
30 | #pod | ||||
31 | #pod The C<namespace::autoclean> pragma will remove all imported symbols at the end | ||||
32 | #pod of the current package's compile cycle. Functions called in the package itself | ||||
33 | #pod will still be bound by their name, but they won't show up as methods on your | ||||
34 | #pod class or instances. | ||||
35 | #pod | ||||
36 | #pod This module is very similar to L<namespace::clean|namespace::clean>, except it | ||||
37 | #pod will clean all imported functions, no matter if you imported them before or | ||||
38 | #pod after you C<use>d the pragma. It will also not touch anything that looks like a | ||||
39 | #pod method. | ||||
40 | #pod | ||||
41 | #pod If you're writing an exporter and you want to clean up after yourself (and your | ||||
42 | #pod peers), you can use the C<-cleanee> switch to specify what package to clean: | ||||
43 | #pod | ||||
44 | #pod package My::MooseX::namespace::autoclean; | ||||
45 | #pod use strict; | ||||
46 | #pod | ||||
47 | #pod use namespace::autoclean (); # no cleanup, just load | ||||
48 | #pod | ||||
49 | #pod sub import { | ||||
50 | #pod namespace::autoclean->import( | ||||
51 | #pod -cleanee => scalar(caller), | ||||
52 | #pod ); | ||||
53 | #pod } | ||||
54 | #pod | ||||
55 | #pod =head1 WHAT IS AND ISN'T CLEANED | ||||
56 | #pod | ||||
57 | #pod C<namespace::autoclean> will leave behind anything that it deems a method. For | ||||
58 | #pod L<Moose> classes, this the based on the C<get_method_list> method | ||||
59 | #pod on from the L<Class::MOP::Class|metaclass>. For non-Moose classes, anything | ||||
60 | #pod defined within the package will be identified as a method. This should match | ||||
61 | #pod Moose's definition of a method. Additionally, the magic subs installed by | ||||
62 | #pod L<overload> will not be cleaned. | ||||
63 | #pod | ||||
64 | #pod =head1 PARAMETERS | ||||
65 | #pod | ||||
66 | #pod =head2 -also => [ ITEM | REGEX | SUB, .. ] | ||||
67 | #pod | ||||
68 | #pod =head2 -also => ITEM | ||||
69 | #pod | ||||
70 | #pod =head2 -also => REGEX | ||||
71 | #pod | ||||
72 | #pod =head2 -also => SUB | ||||
73 | #pod | ||||
74 | #pod Sometimes you don't want to clean imports only, but also helper functions | ||||
75 | #pod you're using in your methods. The C<-also> switch can be used to declare a list | ||||
76 | #pod of functions that should be removed additional to any imports: | ||||
77 | #pod | ||||
78 | #pod use namespace::autoclean -also => ['some_function', 'another_function']; | ||||
79 | #pod | ||||
80 | #pod If only one function needs to be additionally cleaned the C<-also> switch also | ||||
81 | #pod accepts a plain string: | ||||
82 | #pod | ||||
83 | #pod use namespace::autoclean -also => 'some_function'; | ||||
84 | #pod | ||||
85 | #pod In some situations, you may wish for a more I<powerful> cleaning solution. | ||||
86 | #pod | ||||
87 | #pod The C<-also> switch can take a Regex or a CodeRef to match against local | ||||
88 | #pod function names to clean. | ||||
89 | #pod | ||||
90 | #pod use namespace::autoclean -also => qr/^_/ | ||||
91 | #pod | ||||
92 | #pod use namespace::autoclean -also => sub { $_ =~ m{^_} }; | ||||
93 | #pod | ||||
94 | #pod use namespace::autoclean -also => [qr/^_/ , qr/^hidden_/ ]; | ||||
95 | #pod | ||||
96 | #pod use namespace::autoclean -also => [sub { $_ =~ m/^_/ or $_ =~ m/^hidden/ }, sub { uc($_) == $_ } ]; | ||||
97 | #pod | ||||
98 | #pod =head2 -except => [ ITEM | REGEX | SUB, .. ] | ||||
99 | #pod | ||||
100 | #pod =head2 -except => ITEM | ||||
101 | #pod | ||||
102 | #pod =head2 -except => REGEX | ||||
103 | #pod | ||||
104 | #pod =head2 -except => SUB | ||||
105 | #pod | ||||
106 | #pod This takes exactly the same options as C<-also> except that anything this | ||||
107 | #pod matches will I<not> be cleaned. | ||||
108 | #pod | ||||
109 | #pod =head1 CAVEATS | ||||
110 | #pod | ||||
111 | #pod When used with L<Moo> classes, the heuristic used to check for methods won't | ||||
112 | #pod work correctly for methods from roles consumed at compile time. | ||||
113 | #pod | ||||
114 | #pod package My::Class; | ||||
115 | #pod use Moo; | ||||
116 | #pod use namespace::autoclean; | ||||
117 | #pod | ||||
118 | #pod # Bad, any consumed methods will be cleaned | ||||
119 | #pod BEGIN { with 'Some::Role' } | ||||
120 | #pod | ||||
121 | #pod # Good, methods from role will be maintained | ||||
122 | #pod with 'Some::Role'; | ||||
123 | #pod | ||||
124 | #pod Additionally, method detection may not work properly in L<Mouse> classes in | ||||
125 | #pod perls earlier than 5.10. | ||||
126 | #pod | ||||
127 | #pod =head1 SEE ALSO | ||||
128 | #pod | ||||
129 | #pod =for :list | ||||
130 | #pod * L<namespace::clean> | ||||
131 | #pod * L<B::Hooks::EndOfScope> | ||||
132 | #pod * L<namespace::sweep> | ||||
133 | #pod * L<Sub::Exporter::ForMethods> | ||||
134 | #pod * L<Sub::Name> | ||||
135 | #pod * L<Sub::Install> | ||||
136 | #pod * L<Test::CleanNamespaces> | ||||
137 | #pod * L<Dist::Zilla::Plugin::Test::CleanNamespaces> | ||||
138 | #pod | ||||
139 | #pod =cut | ||||
140 | |||||
141 | # spent 38µs (20+19) within namespace::autoclean::import which was called:
# once (20µs+19µs) by String::Markov::BEGIN@9 at line 9 of String/Markov.pm | ||||
142 | 1 | 1µs | my ($class, %args) = @_; | ||
143 | |||||
144 | my $subcast = sub { | ||||
145 | my $i = shift; | ||||
146 | return $i if ref $i eq 'CODE'; | ||||
147 | return sub { $_ =~ $i } if ref $i eq 'Regexp'; | ||||
148 | return sub { $_ eq $i }; | ||||
149 | 1 | 3µs | }; | ||
150 | |||||
151 | my $runtest = sub { | ||||
152 | my ($code, $method_name) = @_; | ||||
153 | local $_ = $method_name; | ||||
154 | return $code->(); | ||||
155 | 1 | 1µs | }; | ||
156 | |||||
157 | 1 | 2µs | my $cleanee = exists $args{-cleanee} ? $args{-cleanee} : scalar caller; | ||
158 | |||||
159 | my @also = map { $subcast->($_) } ( | ||||
160 | exists $args{-also} | ||||
161 | 1 | 1µs | ? (ref $args{-also} eq 'ARRAY' ? @{ $args{-also} } : $args{-also}) | ||
162 | : () | ||||
163 | ); | ||||
164 | |||||
165 | my @except = map { $subcast->($_) } ( | ||||
166 | exists $args{-except} | ||||
167 | 1 | 1µs | ? (ref $args{-except} eq 'ARRAY' ? @{ $args{-except} } : $args{-except}) | ||
168 | : () | ||||
169 | ); | ||||
170 | |||||
171 | # spent 2.38ms (222µs+2.16) within namespace::autoclean::__ANON__[/usr/local/share/perl/5.18.2/namespace/autoclean.pm:183] which was called:
# once (222µs+2.16ms) by B::Hooks::EndOfScope::XS::__ANON__[/usr/local/share/perl/5.18.2/B/Hooks/EndOfScope/XS.pm:17] at line 17 of B/Hooks/EndOfScope/XS.pm | ||||
172 | 1 | 6µs | 1 | 187µs | my $subs = namespace::clean->get_functions($cleanee); # spent 187µs making 1 call to namespace::clean::get_functions |
173 | 1 | 2µs | 1 | 1.24ms | my $method_check = _method_check($cleanee); # spent 1.24ms making 1 call to namespace::autoclean::_method_check |
174 | |||||
175 | 16 | 6µs | my @clean = grep { | ||
176 | 1 | 39µs | my $method = $_; | ||
177 | ! first { $runtest->($_, $method) } @except | ||||
178 | and ( !$method_check->($method) | ||||
179 | 16 | 162µs | 40 | 306µs | or first { $runtest->($_, $method) } @also) # spent 272µs making 16 calls to namespace::autoclean::__ANON__[namespace/autoclean.pm:210], avg 17µs/call
# spent 35µs making 24 calls to List::Util::first, avg 1µs/call |
180 | } keys %$subs; | ||||
181 | |||||
182 | 1 | 13µs | 1 | 422µs | namespace::clean->clean_subroutines($cleanee, @clean); # spent 422µs making 1 call to namespace::clean::clean_subroutines |
183 | 1 | 10µs | 1 | 18µs | }; # spent 18µs making 1 call to B::Hooks::EndOfScope::XS::on_scope_end |
184 | } | ||||
185 | |||||
186 | # spent 1.24ms (928µs+313µs) within namespace::autoclean::_method_check which was called:
# once (928µs+313µs) by namespace::autoclean::__ANON__[/usr/local/share/perl/5.18.2/namespace/autoclean.pm:183] at line 173 | ||||
187 | 1 | 700ns | my $package = shift; | ||
188 | 1 | 1µs | if ( | ||
189 | (defined &Class::MOP::class_of and my $meta = Class::MOP::class_of($package)) | ||||
190 | ) { | ||||
191 | my %methods = map { $_ => 1 } $meta->get_method_list; | ||||
192 | $methods{meta} = 1 | ||||
193 | if $meta->isa('Moose::Meta::Role') && Moose->VERSION < 0.90; | ||||
194 | return sub { $_[0] =~ /^\(/ || $methods{$_[0]} }; | ||||
195 | } | ||||
196 | else { | ||||
197 | 1 | 16µs | 1 | 5µs | my $does = $package->can('does') ? 'does' # spent 5µs making 1 call to UNIVERSAL::can |
198 | : $package->can('DOES') ? 'DOES' | ||||
199 | : undef; | ||||
200 | 1 | 95µs | require Sub::Identify; | ||
201 | # spent 272µs (173+99) within namespace::autoclean::__ANON__[/usr/local/share/perl/5.18.2/namespace/autoclean.pm:210] which was called 16 times, avg 17µs/call:
# 16 times (173µs+99µs) by namespace::autoclean::__ANON__[/usr/local/share/perl/5.18.2/namespace/autoclean.pm:183] at line 179, avg 17µs/call | ||||
202 | 16 | 44µs | 16 | 9µs | return 1 if $_[0] =~ /^\(/; # spent 9µs making 16 calls to namespace::autoclean::CORE:match, avg 544ns/call |
203 | 34 | 188µs | 2 | 44µs | # spent 28µs (11+17) within namespace::autoclean::BEGIN@203 which was called:
# once (11µs+17µs) by String::Markov::BEGIN@9 at line 203 # spent 28µs making 1 call to namespace::autoclean::BEGIN@203
# spent 17µs making 1 call to strict::unimport |
204 | 16 | 23µs | 16 | 75µs | my $code_stash = Sub::Identify::stash_name($coderef); # spent 75µs making 16 calls to Sub::Identify::stash_name, avg 5µs/call |
205 | 16 | 27µs | return 1 if $code_stash eq $package; | ||
206 | 8 | 2µs | return 1 if $code_stash eq 'constant'; | ||
207 | # TODO: consider if we really need this eval | ||||
208 | 16 | 22µs | 8 | 15µs | return 1 if $does && eval { $package->$does($code_stash) }; # spent 15µs making 8 calls to Moo::Object::does, avg 2µs/call |
209 | 8 | 20µs | return 0; | ||
210 | 1 | 11µs | }; | ||
211 | } | ||||
212 | } | ||||
213 | |||||
214 | 1 | 3µs | 1; | ||
215 | |||||
216 | 1 | 12µs | 1 | 156µs | __END__ # spent 156µs making 1 call to B::Hooks::EndOfScope::XS::__ANON__[B/Hooks/EndOfScope/XS.pm:17] |
# spent 9µs within namespace::autoclean::CORE:match which was called 16 times, avg 544ns/call:
# 16 times (9µs+0s) by namespace::autoclean::__ANON__[/usr/local/share/perl/5.18.2/namespace/autoclean.pm:210] at line 202, avg 544ns/call |