drop Package::Stash dependency
[p5sagit/namespace-clean.git] / lib / namespace / clean.pm
CommitLineData
40aef9d6 1package namespace::clean;
40aef9d6 2
3use warnings;
4use strict;
5
77b619d7 6our $VERSION = '0.27';
18377f5b 7$VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
8
727a1a2f 9our $STORAGE_VAR = '__NAMESPACE_CLEAN_STORAGE';
fa84e425 10
727a1a2f 11use B::Hooks::EndOfScope 'on_scope_end';
9887772b 12
df4cbc4e 13use namespace::clean::_Util qw( DEBUGGER_NEEDS_CV_RENAME DEBUGGER_NEEDS_CV_PIVOT );
80e4e267 14
1ae6a568 15# Built-in debugger CV-retrieval fixups necessary before perl 5.15.5:
80e4e267 16# since we are deleting the glob where the subroutine was originally
1ae6a568 17# defined, the assumptions below no longer hold.
80e4e267 18#
1ae6a568 19# In 5.8.9 ~ 5.13.5 (inclusive) the debugger assumes that a CV can
20# always be found under sub_fullname($sub)
21# Workaround: use sub naming to properly name the sub hidden in the package's
22# deleted-stash
23#
24# In the rest of the range ( ... ~ 5.8.8 and 5.13.6 ~ 5.15.4 ) the debugger
25# assumes the name of the glob passed to entersub can be used to find the CV
26# Workaround: realias the original glob to the deleted-stash slot
27#
aea0cfbe 28# While the errors manifest themselves inside perl5db.pl, they are caused by
29# problems inside the interpreter. If enabled ($^P & 0x01) and existent,
30# the DB::sub sub will be called by the interpreter for any sub call rather
31# that call the sub directly. It is provided the real sub to call in $DB::sub,
32# but the value given has the issues described above. We only have to enable
33# the workaround if DB::sub will be used.
34#
1ae6a568 35# Can not tie constants to the current value of $^P directly,
36# as the debugger can be enabled during runtime (kinda dubious)
80e4e267 37#
017bd598 38
39my $RemoveSubs = sub {
de673bbf 40 my $cleanee = shift;
41 my $store = shift;
22212124 42 my $cleanee_stash = \%{"${cleanee}::"};
43 my $deleted_stash_name;
017bd598 44 my $deleted_stash;
45
22212124 46 no strict 'refs';
de673bbf 47 SYMBOL:
48 for my $f (@_) {
017bd598 49
de673bbf 50 # ignore already removed symbols
51 next SYMBOL if $store->{exclude}{ $f };
de673bbf 52
22212124 53 next SYMBOL
54 unless exists &{"${cleanee}::$f"};
55
56 my $sub = \&{"${cleanee}::$f"};
226432f6 57
80e4e267 58 my $need_debugger_fixup =
df4cbc4e 59 ( DEBUGGER_NEEDS_CV_RENAME or DEBUGGER_NEEDS_CV_PIVOT )
64c1bcfc 60 &&
aea0cfbe 61 $^P & 0x01
62 &&
63 defined &DB::sub
80e4e267 64 &&
22212124 65 ref(my $globref = \$cleanee_stash->{$f}) eq 'GLOB'
66 &&
67 ( $deleted_stash_name ||= "namespace::clean::deleted::$cleanee" )
1ae6a568 68 &&
22212124 69 ( $deleted_stash ||= \%{"${deleted_stash_name}::"} )
80e4e267 70 ;
71
1ae6a568 72 # convince the Perl debugger to work
73 # see the comment on top
74 if ( DEBUGGER_NEEDS_CV_RENAME and $need_debugger_fixup ) {
75 #
76 # Note - both get_subname and set_subname are only compiled when CV_RENAME
77 # is true ( the 5.8.9 ~ 5.12 range ). On other perls this entire block is
78 # constant folded away, and so are the definitions in ::_Util
79 #
80 # Do not be surprised that they are missing without DEBUGGER_NEEDS_CV_RENAME
81 #
22212124 82 namespace::clean::_Util::get_subname( $sub ) eq ( $cleanee . "::$f" )
1ae6a568 83 and
22212124 84 *{"${deleted_stash_name}::$f"} =
85 namespace::clean::_Util::set_subname( $deleted_stash_name . "::$f", $sub );
de673bbf 86 }
1ae6a568 87 elsif ( DEBUGGER_NEEDS_CV_PIVOT and $need_debugger_fixup ) {
22212124 88 *{"${deleted_stash_name}::$f"} = $sub;
1ae6a568 89 }
d6aecfbf 90
d64ad6f8 91
22212124 92 my @symbols = do {
93 my $glob = *{"${cleanee}::$f"};
94 grep defined,
95 map *{$glob}{$_},
96 qw(SCALAR ARRAY HASH IO);
97 };
98
99 delete $cleanee_stash->{$f};
d64ad6f8 100
80e4e267 101 # if this perl needs no renaming trick we need to
102 # rename the original glob after the fact
1ae6a568 103 DEBUGGER_NEEDS_CV_PIVOT
104 and
105 $need_debugger_fixup
106 and
22212124 107 *$globref = $deleted_stash->{$f};
80e4e267 108
22212124 109 *{"${cleanee}::$f"} = $_ for @symbols;
de673bbf 110 }
111};
53e92ec5 112
fcfe7810 113sub clean_subroutines {
114 my ($nc, $cleanee, @subs) = @_;
115 $RemoveSubs->($cleanee, {}, @subs);
116}
117
de673bbf 118sub import {
119 my ($pragma, @args) = @_;
53e92ec5 120
de673bbf 121 my (%args, $is_explicit);
fcfe7810 122
123 ARG:
124 while (@args) {
125
126 if ($args[0] =~ /^\-/) {
127 my $key = shift @args;
128 my $value = shift @args;
129 $args{ $key } = $value;
130 }
131 else {
132 $is_explicit++;
133 last ARG;
134 }
9b680ffe 135 }
136
fcfe7810 137 my $cleanee = exists $args{ -cleanee } ? $args{ -cleanee } : scalar caller;
de673bbf 138 if ($is_explicit) {
aa2aafae 139 on_scope_end {
de673bbf 140 $RemoveSubs->($cleanee, {}, @args);
aa2aafae 141 };
9b680ffe 142 }
de673bbf 143 else {
144
145 # calling class, all current functions and our storage
146 my $functions = $pragma->get_functions($cleanee);
147 my $store = $pragma->get_class_store($cleanee);
148
149 # except parameter can be array ref or single value
150 my %except = map {( $_ => 1 )} (
151 $args{ -except }
152 ? ( ref $args{ -except } eq 'ARRAY' ? @{ $args{ -except } } : $args{ -except } )
153 : ()
154 );
155
156 # register symbols for removal, if they have a CODE entry
157 for my $f (keys %$functions) {
158 next if $except{ $f };
22212124 159 next unless exists &{"${cleanee}::$f"};
de673bbf 160 $store->{remove}{ $f } = 1;
161 }
162
a6b490ab 163 on_scope_end {
164 $RemoveSubs->($cleanee, $store, keys %{ $store->{remove} });
165 };
de673bbf 166
167 return 1;
168 }
9b680ffe 169}
170
9b680ffe 171sub unimport {
fcfe7810 172 my ($pragma, %args) = @_;
9b680ffe 173
6c0ece9b 174 # the calling class, the current functions and our storage
fcfe7810 175 my $cleanee = exists $args{ -cleanee } ? $args{ -cleanee } : scalar caller;
9b680ffe 176 my $functions = $pragma->get_functions($cleanee);
177 my $store = $pragma->get_class_store($cleanee);
178
6c0ece9b 179 # register all unknown previous functions as excluded
9b680ffe 180 for my $f (keys %$functions) {
181 next if $store->{remove}{ $f }
182 or $store->{exclude}{ $f };
183 $store->{exclude}{ $f } = 1;
184 }
185
186 return 1;
187}
188
9b680ffe 189sub get_class_store {
190 my ($pragma, $class) = @_;
22212124 191 no strict 'refs';
192 return \%{"${class}::${STORAGE_VAR}"};
40aef9d6 193}
194
40aef9d6 195sub get_functions {
196 my ($pragma, $class) = @_;
197
22212124 198 no strict 'refs';
40aef9d6 199 return {
22212124 200 map +($_ => \&{"${class}::$_"}),
201 grep exists &{"${class}::$_"},
202 sort keys %{"${class}::"}
40aef9d6 203 };
204}
205
b3b7a821 206'Danger! Laws of Thermodynamics may not apply.'
207
208__END__
209
210=head1 NAME
211
212namespace::clean - Keep imports and functions out of your namespace
213
214=head1 SYNOPSIS
215
216 package Foo;
217 use warnings;
218 use strict;
219
220 use Carp qw(croak); # 'croak' will be removed
221
222 sub bar { 23 } # 'bar' will be removed
223
224 # remove all previously defined functions
225 use namespace::clean;
226
227 sub baz { bar() } # 'baz' still defined, 'bar' still bound
228
229 # begin to collection function names from here again
230 no namespace::clean;
231
232 sub quux { baz() } # 'quux' will be removed
233
234 # remove all functions defined after the 'no' unimport
235 use namespace::clean;
236
237 # Will print: 'No', 'No', 'Yes' and 'No'
238 print +(__PACKAGE__->can('croak') ? 'Yes' : 'No'), "\n";
239 print +(__PACKAGE__->can('bar') ? 'Yes' : 'No'), "\n";
240 print +(__PACKAGE__->can('baz') ? 'Yes' : 'No'), "\n";
241 print +(__PACKAGE__->can('quux') ? 'Yes' : 'No'), "\n";
242
243 1;
244
245=head1 DESCRIPTION
246
247=head2 Keeping packages clean
248
249When you define a function, or import one, into a Perl package, it will
250naturally also be available as a method. This does not per se cause
251problems, but it can complicate subclassing and, for example, plugin
252classes that are included via multiple inheritance by loading them as
253base classes.
254
255The C<namespace::clean> pragma will remove all previously declared or
256imported symbols at the end of the current package's compile cycle.
257Functions called in the package itself will still be bound by their
258name, but they won't show up as methods on your class or instances.
259
260By unimporting via C<no> you can tell C<namespace::clean> to start
261collecting functions for the next C<use namespace::clean;> specification.
262
263You can use the C<-except> flag to tell C<namespace::clean> that you
264don't want it to remove a certain function or method. A common use would
265be a module exporting an C<import> method along with some functions:
266
267 use ModuleExportingImport;
268 use namespace::clean -except => [qw( import )];
269
270If you just want to C<-except> a single sub, you can pass it directly.
271For more than one value you have to use an array reference.
272
253c58bc 273=head3 Late binding caveat
274
275Note that the L<technique used by this module|/IMPLEMENTATION DETAILS> relies
276on perl having resolved all names to actual code references during the
277compilation of a scope. While this is almost always what the interpreter does,
278there are some exceptions, notably the L<sort SUBNAME|perlfunc/sort> style of
279the C<sort> built-in invocation. The following example will not work, because
280C<sort> does not try to resolve the function name to an actual code reference
281until B<runtime>.
282
283 use MyApp::Utils 'my_sorter';
284 use namespace::clean;
285
286 my @sorted = sort my_sorter @list;
287
288You need to work around this by forcing a compile-time resolution like so:
289
041ac8b7 290 use MyApp::Utils 'my_sorter';
253c58bc 291 use namespace::clean;
292
041ac8b7 293 my $my_sorter_cref = \&my_sorter;
253c58bc 294
295 my @sorted = sort $my_sorter_cref @list;
296
b3b7a821 297=head2 Explicitly removing functions when your scope is compiled
298
299It is also possible to explicitly tell C<namespace::clean> what packages
300to remove when the surrounding scope has finished compiling. Here is an
301example:
302
303 package Foo;
304 use strict;
305
306 # blessed NOT available
307
308 sub my_class {
309 use Scalar::Util qw( blessed );
310 use namespace::clean qw( blessed );
311
312 # blessed available
313 return blessed shift;
314 }
315
316 # blessed NOT available
317
318=head2 Moose
319
320When using C<namespace::clean> together with L<Moose> you want to keep
321the installed C<meta> method. So your classes should look like:
322
323 package Foo;
324 use Moose;
325 use namespace::clean -except => 'meta';
326 ...
327
328Same goes for L<Moose::Role>.
329
330=head2 Cleaning other packages
331
332You can tell C<namespace::clean> that you want to clean up another package
333instead of the one importing. To do this you have to pass in the C<-cleanee>
334option like this:
335
336 package My::MooseX::namespace::clean;
337 use strict;
338
339 use namespace::clean (); # no cleanup, just load
340
341 sub import {
342 namespace::clean->import(
343 -cleanee => scalar(caller),
344 -except => 'meta',
345 );
346 }
347
348If you don't care about C<namespace::clean>s discover-and-C<-except> logic, and
349just want to remove subroutines, try L</clean_subroutines>.
350
351=head1 METHODS
352
353=head2 clean_subroutines
354
355This exposes the actual subroutine-removal logic.
356
357 namespace::clean->clean_subroutines($cleanee, qw( subA subB ));
358
359will remove C<subA> and C<subB> from C<$cleanee>. Note that this will remove the
360subroutines B<immediately> and not wait for scope end. If you want to have this
361effect at a specific time (e.g. C<namespace::clean> acts on scope compile end)
362it is your responsibility to make sure it runs at that time.
363
364=head2 import
365
366Makes a snapshot of the current defined functions and installs a
367L<B::Hooks::EndOfScope> hook in the current scope to invoke the cleanups.
368
369
370=head2 unimport
371
372This method will be called when you do a
373
374 no namespace::clean;
375
376It will start a new section of code that defines functions to clean up.
377
378=head2 get_class_store
379
380This returns a reference to a hash in a passed package containing
381information about function names included and excluded from removal.
382
383=head2 get_functions
384
385Takes a class as argument and returns all currently defined functions
386in it as a hash reference with the function name as key and a typeglob
387reference to the symbol as value.
388
6c0ece9b 389=head1 IMPLEMENTATION DETAILS
390
04312494 391This module works through the effect that a
6c0ece9b 392
393 delete $SomePackage::{foo};
394
395will remove the C<foo> symbol from C<$SomePackage> for run time lookups
396(e.g., method calls) but will leave the entry alive to be called by
472d4b1e 397already resolved names in the package itself. C<namespace::clean> will
398restore and therefor in effect keep all glob slots that aren't C<CODE>.
6c0ece9b 399
400A test file has been added to the perl core to ensure that this behaviour
401will be stable in future releases.
402
403Just for completeness sake, if you want to remove the symbol completely,
404use C<undef> instead.
405
40aef9d6 406=head1 SEE ALSO
407
705fe1b1 408L<B::Hooks::EndOfScope>
40aef9d6 409
04312494 410=head1 THANKS
40aef9d6 411
04312494 412Many thanks to Matt S Trout for the inspiration on the whole idea.
40aef9d6 413
fa84e425 414=head1 AUTHORS
415
416=over
417
418=item *
419
420Robert 'phaylon' Sedlacek <rs@474.at>
421
422=item *
423
424Florian Ragwitz <rafl@debian.org>
425
426=item *
427
428Jesse Luehrs <doy@tozt.net>
429
430=item *
431
432Peter Rabbitson <ribasushi@cpan.org>
433
b2e54862 434=item *
435
436Father Chrysostomos <sprout@cpan.org>
437
fa84e425 438=back
439
440=head1 COPYRIGHT AND LICENSE
441
b2e54862 442This software is copyright (c) 2011 by L</AUTHORS>
fa84e425 443
444This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.