Document Moose::Meta::Role get_*_method_modifiers fix
[gitmo/Moose.git] / lib / Moose / Exporter.pm
CommitLineData
e606ae5f 1package Moose::Exporter;
2
3use strict;
4use warnings;
5
e6ab9ca5 6our $VERSION = '0.83';
ae18d5ec 7$VERSION = eval $VERSION;
8our $AUTHORITY = 'cpan:STEVAN';
9
e606ae5f 10use Class::MOP;
11use List::MoreUtils qw( first_index uniq );
12use Moose::Util::MetaRole;
13use Sub::Exporter;
9f2230e9 14use Sub::Name qw(subname);
e606ae5f 15
16my %EXPORT_SPEC;
17
18sub setup_import_methods {
19 my ( $class, %args ) = @_;
20
21 my $exporting_package = $args{exporting_package} ||= caller();
22
23 my ( $import, $unimport ) = $class->build_import_methods(%args);
24
25 no strict 'refs';
26 *{ $exporting_package . '::import' } = $import;
27 *{ $exporting_package . '::unimport' } = $unimport;
28}
29
30sub build_import_methods {
31 my ( $class, %args ) = @_;
32
33 my $exporting_package = $args{exporting_package} ||= caller();
34
35 $EXPORT_SPEC{$exporting_package} = \%args;
36
37 my @exports_from = $class->_follow_also( $exporting_package );
38
39 my $export_recorder = {};
40
45975bce 41 my ( $exports, $is_removable, $groups )
e05fb8ae 42 = $class->_make_sub_exporter_params(
f44ec924 43 [ @exports_from, $exporting_package ], $export_recorder );
e606ae5f 44
45 my $exporter = Sub::Exporter::build_exporter(
46 {
47 exports => $exports,
45975bce 48 groups => { default => [':all'], %$groups }
e606ae5f 49 }
50 );
51
52 # $args{_export_to_main} exists for backwards compat, because
53 # Moose::Util::TypeConstraints did export to main (unlike Moose &
54 # Moose::Role).
55 my $import = $class->_make_import_sub( $exporting_package, $exporter,
56 \@exports_from, $args{_export_to_main} );
57
58 my $unimport = $class->_make_unimport_sub( $exporting_package, $exports,
e05fb8ae 59 $is_removable, $export_recorder );
e606ae5f 60
61 return ( $import, $unimport )
62}
63
64{
65 my $seen = {};
66
67 sub _follow_also {
68 my $class = shift;
69 my $exporting_package = shift;
70
71 local %$seen = ( $exporting_package => 1 );
72
73 return uniq( _follow_also_real($exporting_package) );
74 }
75
76 sub _follow_also_real {
77 my $exporting_package = shift;
78
ba1a3c2f 79 if (!exists $EXPORT_SPEC{$exporting_package}) {
80 my $loaded = Class::MOP::is_class_loaded($exporting_package);
81
82 die "Package in also ($exporting_package) does not seem to "
83 . "use Moose::Exporter"
84 . ($loaded ? "" : " (is it loaded?)");
85 }
e606ae5f 86
87 my $also = $EXPORT_SPEC{$exporting_package}{also};
88
89 return unless defined $also;
90
91 my @also = ref $also ? @{$also} : $also;
92
93 for my $package (@also)
94 {
f5d03831 95 die "Circular reference in also parameter to Moose::Exporter between $exporting_package and $package"
e606ae5f 96 if $seen->{$package};
97
98 $seen->{$package} = 1;
99 }
100
101 return @also, map { _follow_also_real($_) } @also;
102 }
103}
104
105sub _make_sub_exporter_params {
106 my $class = shift;
107 my $packages = shift;
108 my $export_recorder = shift;
109
45975bce 110 my %groups;
e606ae5f 111 my %exports;
e05fb8ae 112 my %is_removable;
e606ae5f 113
114 for my $package ( @{$packages} ) {
115 my $args = $EXPORT_SPEC{$package}
116 or die "The $package package does not use Moose::Exporter\n";
117
45975bce 118 # one group for each 'also' package
119 $groups{$package} = [
120 @{ $args->{with_caller} || [] },
121 @{ $args->{with_meta} || [] },
122 @{ $args->{as_is} || [] },
123 map ":$_",
124 keys %{ $args->{groups} || {} }
125 ];
126
e606ae5f 127 for my $name ( @{ $args->{with_caller} } ) {
128 my $sub = do {
129 no strict 'refs';
130 \&{ $package . '::' . $name };
131 };
132
133 my $fq_name = $package . '::' . $name;
134
135 $exports{$name} = $class->_make_wrapped_sub(
136 $fq_name,
137 $sub,
138 $export_recorder,
139 );
e05fb8ae 140
141 $is_removable{$name} = 1;
e606ae5f 142 }
143
45975bce 144 for my $name ( @{ $args->{with_meta} } ) {
145 my $sub = do {
146 no strict 'refs';
147 \&{ $package . '::' . $name };
148 };
149
150 my $fq_name = $package . '::' . $name;
151
152 $exports{$name} = $class->_make_wrapped_sub_with_meta(
153 $fq_name,
154 $sub,
155 $export_recorder,
156 );
157
158 $is_removable{$name} = 1;
159 }
160
e606ae5f 161 for my $name ( @{ $args->{as_is} } ) {
162 my $sub;
163
164 if ( ref $name ) {
165 $sub = $name;
e05fb8ae 166
167 # Even though Moose re-exports things from Carp &
168 # Scalar::Util, we don't want to remove those at
169 # unimport time, because the importing package may
170 # have imported them explicitly ala
171 #
172 # use Carp qw( confess );
173 #
174 # This is a hack. Since we can't know whether they
175 # really want to keep these subs or not, we err on the
176 # safe side and leave them in.
177 my $coderef_pkg;
178 ( $coderef_pkg, $name ) = Class::MOP::get_code_info($name);
179
180 $is_removable{$name} = $coderef_pkg eq $package ? 1 : 0;
e606ae5f 181 }
182 else {
183 $sub = do {
184 no strict 'refs';
185 \&{ $package . '::' . $name };
186 };
e05fb8ae 187
188 $is_removable{$name} = 1;
e606ae5f 189 }
190
191 $export_recorder->{$sub} = 1;
192
193 $exports{$name} = sub {$sub};
194 }
45975bce 195
196 for my $name ( keys %{ $args->{groups} } ) {
197 my $group = $args->{groups}{$name};
198
199 if (ref $group eq 'CODE') {
200 $groups{$name} = $class->_make_wrapped_group(
201 $package,
202 $group,
203 $export_recorder,
204 \%exports,
205 \%is_removable
206 );
207 }
208 elsif (ref $group eq 'ARRAY') {
209 $groups{$name} = $group;
210 }
211 }
e606ae5f 212 }
213
45975bce 214 return ( \%exports, \%is_removable, \%groups );
e606ae5f 215}
216
96bb13ea 217our $CALLER;
218
219sub _make_wrapped_sub {
b4f00a34 220 my $self = shift;
96bb13ea 221 my $fq_name = shift;
222 my $sub = shift;
223 my $export_recorder = shift;
224
225 # We need to set the package at import time, so that when
226 # package Foo imports has(), we capture "Foo" as the
227 # package. This lets other packages call Foo::has() and get
228 # the right package. This is done for backwards compatibility
229 # with existing production code, not because this is a good
230 # idea ;)
231 return sub {
232 my $caller = $CALLER;
233
6de00734 234 my $wrapper = $self->_curry_wrapper($sub, $fq_name, $caller);
b4f00a34 235
9f2230e9 236 my $sub = subname($fq_name => $wrapper);
96bb13ea 237
238 $export_recorder->{$sub} = 1;
239
240 return $sub;
241 };
242}
e606ae5f 243
45975bce 244sub _make_wrapped_sub_with_meta {
245 my $self = shift;
246 my $fq_name = shift;
247 my $sub = shift;
248 my $export_recorder = shift;
249
250 return sub {
251 my $caller = $CALLER;
252
253 my $wrapper = $self->_late_curry_wrapper($sub, $fq_name,
254 sub { Class::MOP::class_of(shift) } => $caller);
255
256 my $sub = subname($fq_name => $wrapper);
257
258 $export_recorder->{$sub} = 1;
259
260 return $sub;
261 };
262}
263
264sub _make_wrapped_group {
265 my $class = shift;
266 my $package = shift; # package calling use Moose::Exporter
267 my $sub = shift;
268 my $export_recorder = shift;
269 my $keywords = shift;
270 my $is_removable = shift;
271
272 return sub {
273 my $caller = $CALLER; # package calling use PackageUsingMooseExporter -group => {args}
274
275 # there are plenty of ways to deal with telling the code which
276 # package it lives in. the last arg (collector hashref) is
277 # otherwise unused, so we'll stick the original package in
278 # there and act like 'with_caller' by putting the calling
279 # package name as the first arg
280 $_[0] = $caller;
281 $_[3]{from} = $package;
282
283 my $named_code = $sub->(@_);
284 $named_code ||= { };
285
286 # send invalid return value error up to Sub::Exporter
287 unless (ref $named_code eq 'HASH') {
288 return $named_code;
289 }
290
291 for my $name (keys %$named_code) {
292 my $code = $named_code->{$name};
293
294 my $fq_name = $package . '::' . $name;
295 my $wrapper = $class->_curry_wrapper(
296 $code,
297 $fq_name,
298 $caller
299 );
300
301 my $sub = subname( $fq_name => $wrapper );
302 $named_code->{$name} = $sub;
303
304 # mark each coderef as ours
305 $keywords->{$name} = 1;
306 $is_removable->{$name} = 1;
307 $export_recorder->{$sub} = 1;
308 }
309
310 return $named_code;
311 };
312}
313
6de00734 314sub _curry_wrapper {
badbc528 315 my $class = shift;
b4f00a34 316 my $sub = shift;
317 my $fq_name = shift;
6de00734 318 my @extra = @_;
b4f00a34 319
6de00734 320 my $wrapper = sub { $sub->(@extra, @_) };
badbc528 321 if (my $proto = prototype $sub) {
2d7e979b 322 # XXX - Perl's prototype sucks. Use & to make set_prototype
6de00734 323 # ignore the fact that we're passing "private variables"
2d7e979b 324 &Scalar::Util::set_prototype($wrapper, $proto);
badbc528 325 }
326 return $wrapper;
b4f00a34 327}
328
45975bce 329sub _late_curry_wrapper {
330 my $class = shift;
331 my $sub = shift;
332 my $fq_name = shift;
333 my $extra = shift;
334 my @ex_args = @_;
335
336 my $wrapper = sub {
337 # resolve curried arguments at runtime via this closure
338 my @curry = ( $extra->( @ex_args ) );
339 return $sub->(@curry, @_);
340 };
341
342 if (my $proto = prototype $sub) {
343 # XXX - Perl's prototype sucks. Use & to make set_prototype
344 # ignore the fact that we're passing "private variables"
345 &Scalar::Util::set_prototype($wrapper, $proto);
346 }
347 return $wrapper;
348}
349
96bb13ea 350sub _make_import_sub {
351 shift;
352 my $exporting_package = shift;
353 my $exporter = shift;
354 my $exports_from = shift;
355 my $export_to_main = shift;
356
357 return sub {
358
359 # I think we could use Sub::Exporter's collector feature
360 # to do this, but that would be rather gross, since that
361 # feature isn't really designed to return a value to the
362 # caller of the exporter sub.
363 #
364 # Also, this makes sure we preserve backwards compat for
365 # _get_caller, so it always sees the arguments in the
366 # expected order.
367 my $traits;
368 ( $traits, @_ ) = _strip_traits(@_);
369
8f30b86e 370 my $metaclass;
371 ( $metaclass, @_ ) = _strip_metaclass(@_);
372
96bb13ea 373 # Normally we could look at $_[0], but in some weird cases
374 # (involving goto &Moose::import), $_[0] ends as something
375 # else (like Squirrel).
376 my $class = $exporting_package;
377
378 $CALLER = _get_caller(@_);
379
380 # this works because both pragmas set $^H (see perldoc
381 # perlvar) which affects the current compilation -
382 # i.e. the file who use'd us - which is why we don't need
383 # to do anything special to make it affect that file
384 # rather than this one (which is already compiled)
385
386 strict->import;
387 warnings->import;
388
389 # we should never export to main
390 if ( $CALLER eq 'main' && !$export_to_main ) {
391 warn
392 qq{$class does not export its sugar to the 'main' package.\n};
393 return;
394 }
e606ae5f 395
96bb13ea 396 my $did_init_meta;
397 for my $c ( grep { $_->can('init_meta') } $class, @{$exports_from} ) {
816208bc 398 # init_meta can apply a role, which when loaded uses
399 # Moose::Exporter, which in turn sets $CALLER, so we need
400 # to protect against that.
fdeb8354 401 local $CALLER = $CALLER;
89bcd625 402 $c->init_meta( for_class => $CALLER, metaclass => $metaclass );
96bb13ea 403 $did_init_meta = 1;
404 }
e606ae5f 405
96bb13ea 406 if ( $did_init_meta && @{$traits} ) {
407 # The traits will use Moose::Role, which in turn uses
408 # Moose::Exporter, which in turn sets $CALLER, so we need
409 # to protect against that.
410 local $CALLER = $CALLER;
411 _apply_meta_traits( $CALLER, $traits );
412 }
413 elsif ( @{$traits} ) {
70ea9161 414 require Moose;
96bb13ea 415 Moose->throw_error(
416 "Cannot provide traits when $class does not have an init_meta() method"
417 );
418 }
e606ae5f 419
96bb13ea 420 goto $exporter;
421 };
e606ae5f 422}
423
96bb13ea 424
e606ae5f 425sub _strip_traits {
426 my $idx = first_index { $_ eq '-traits' } @_;
427
428 return ( [], @_ ) unless $idx >= 0 && $#_ >= $idx + 1;
429
430 my $traits = $_[ $idx + 1 ];
431
432 splice @_, $idx, 2;
433
434 $traits = [ $traits ] unless ref $traits;
435
436 return ( $traits, @_ );
437}
438
8f30b86e 439sub _strip_metaclass {
440 my $idx = first_index { $_ eq '-metaclass' } @_;
441
442 return ( undef, @_ ) unless $idx >= 0 && $#_ >= $idx + 1;
443
444 my $metaclass = $_[ $idx + 1 ];
445
446 splice @_, $idx, 2;
447
448 return ( $metaclass, @_ );
449}
450
e606ae5f 451sub _apply_meta_traits {
452 my ( $class, $traits ) = @_;
453
454 return unless @{$traits};
455
2571a16d 456 my $meta = Class::MOP::class_of($class);
e606ae5f 457
458 my $type = ( split /::/, ref $meta )[-1]
c245d69b 459 or Moose->throw_error(
e606ae5f 460 'Cannot determine metaclass type for trait application . Meta isa '
4c0b3599 461 . ref $meta );
e606ae5f 462
463 my @resolved_traits
464 = map { Moose::Util::resolve_metatrait_alias( $type => $_ ) }
465 @$traits;
466
467 return unless @resolved_traits;
468
469 Moose::Util::MetaRole::apply_metaclass_roles(
470 for_class => $class,
471 metaclass_roles => \@resolved_traits,
472 );
473}
474
475sub _get_caller {
476 # 1 extra level because it's called by import so there's a layer
477 # of indirection
478 my $offset = 1;
479
480 return
481 ( ref $_[1] && defined $_[1]->{into} ) ? $_[1]->{into}
482 : ( ref $_[1] && defined $_[1]->{into_level} )
483 ? caller( $offset + $_[1]->{into_level} )
484 : caller($offset);
485}
486
487sub _make_unimport_sub {
488 shift;
489 my $exporting_package = shift;
490 my $exports = shift;
e05fb8ae 491 my $is_removable = shift;
e606ae5f 492 my $export_recorder = shift;
493
494 return sub {
495 my $caller = scalar caller();
496 Moose::Exporter->_remove_keywords(
497 $caller,
498 [ keys %{$exports} ],
e05fb8ae 499 $is_removable,
e606ae5f 500 $export_recorder,
501 );
502 };
503}
504
505sub _remove_keywords {
506 shift;
507 my $package = shift;
508 my $keywords = shift;
e05fb8ae 509 my $is_removable = shift;
e606ae5f 510 my $recorded_exports = shift;
511
512 no strict 'refs';
513
514 foreach my $name ( @{ $keywords } ) {
e05fb8ae 515 next unless $is_removable->{$name};
e606ae5f 516
517 if ( defined &{ $package . '::' . $name } ) {
518 my $sub = \&{ $package . '::' . $name };
519
520 # make sure it is from us
521 next unless $recorded_exports->{$sub};
522
523 # and if it is from us, then undef the slot
524 delete ${ $package . '::' }{$name};
525 }
526 }
527}
528
e2fa092d 529sub import {
530 strict->import;
531 warnings->import;
532}
533
e606ae5f 5341;
535
536__END__
537
538=head1 NAME
539
540Moose::Exporter - make an import() and unimport() just like Moose.pm
541
542=head1 SYNOPSIS
543
544 package MyApp::Moose;
545
e606ae5f 546 use Moose ();
547 use Moose::Exporter;
548
549 Moose::Exporter->setup_import_methods(
82ad7804 550 with_caller => [ 'has_rw', 'sugar2' ],
e606ae5f 551 as_is => [ 'sugar3', \&Some::Random::thing ],
552 also => 'Moose',
553 );
554
82ad7804 555 sub has_rw {
6daad0b9 556 my ($caller, $name, %options) = @_;
4a8a45bc 557 Class::MOP::class_of($caller)->add_attribute($name,
82ad7804 558 is => 'rw',
559 %options,
560 );
561 }
562
e606ae5f 563 # then later ...
564 package MyApp::User;
565
566 use MyApp::Moose;
567
568 has 'name';
6daad0b9 569 has_rw 'size';
e606ae5f 570 thing;
571
572 no MyApp::Moose;
573
574=head1 DESCRIPTION
575
fd7ab111 576This module encapsulates the exporting of sugar functions in a
577C<Moose.pm>-like manner. It does this by building custom C<import> and
578C<unimport> methods for your module, based on a spec you provide.
e606ae5f 579
24aef5e1 580It also lets you "stack" Moose-alike modules so you can export
e606ae5f 581Moose's sugar as well as your own, along with sugar from any random
582C<MooseX> module, as long as they all use C<Moose::Exporter>.
583
10e0127a 584To simplify writing exporter modules, C<Moose::Exporter> also imports
585C<strict> and C<warnings> into your exporter module, as well as into
586modules that use it.
587
e606ae5f 588=head1 METHODS
589
590This module provides two public methods:
591
4b68e0de 592=over 4
593
594=item B<< Moose::Exporter->setup_import_methods(...) >>
e606ae5f 595
596When you call this method, C<Moose::Exporter> build custom C<import>
597and C<unimport> methods for your module. The import method will export
598the functions you specify, and you can also tell it to export
599functions exported by some other module (like C<Moose.pm>).
600
601The C<unimport> method cleans the callers namespace of all the
602exported functions.
603
604This method accepts the following parameters:
605
4b68e0de 606=over 8
e606ae5f 607
608=item * with_caller => [ ... ]
609
610This a list of function I<names only> to be exported wrapped and then
611exported. The wrapper will pass the name of the calling package as the
612first argument to the function. Many sugar functions need to know
613their caller so they can get the calling package's metaclass object.
614
615=item * as_is => [ ... ]
616
617This a list of function names or sub references to be exported
618as-is. You can identify a subroutine by reference, which is handy to
619re-export some other module's functions directly by reference
620(C<\&Some::Package::function>).
621
e05fb8ae 622If you do export some other packages function, this function will
623never be removed by the C<unimport> method. The reason for this is we
624cannot know if the caller I<also> explicitly imported the sub
625themselves, and therefore wants to keep it.
626
e606ae5f 627=item * also => $name or \@names
628
629This is a list of modules which contain functions that the caller
630wants to export. These modules must also use C<Moose::Exporter>. The
631most common use case will be to export the functions from C<Moose.pm>.
ae8817b6 632Functions specified by C<with_caller> or C<as_is> take precedence over
633functions exported by modules specified by C<also>, so that a module
634can selectively override functions exported by another module.
e606ae5f 635
636C<Moose::Exporter> also makes sure all these functions get removed
637when C<unimport> is called.
638
639=back
640
4b68e0de 641=item B<< Moose::Exporter->build_import_methods(...) >>
e606ae5f 642
643Returns two code refs, one for import and one for unimport.
644
645Used by C<setup_import_methods>.
646
4b68e0de 647=back
648
e606ae5f 649=head1 IMPORTING AND init_meta
650
651If you want to set an alternative base object class or metaclass
652class, simply define an C<init_meta> method in your class. The
653C<import> method that C<Moose::Exporter> generates for you will call
654this method (if it exists). It will always pass the caller to this
655method via the C<for_class> parameter.
656
657Most of the time, your C<init_meta> method will probably just call C<<
658Moose->init_meta >> to do the real work:
659
660 sub init_meta {
661 shift; # our class name
662 return Moose->init_meta( @_, metaclass => 'My::Metaclass' );
663 }
664
665=head1 METACLASS TRAITS
666
667The C<import> method generated by C<Moose::Exporter> will allow the
668user of your module to specify metaclass traits in a C<-traits>
669parameter passed as part of the import:
670
671 use Moose -traits => 'My::Meta::Trait';
672
673 use Moose -traits => [ 'My::Meta::Trait', 'My::Other::Trait' ];
674
675These traits will be applied to the caller's metaclass
676instance. Providing traits for an exporting class that does not create
677a metaclass for the caller is an error.
678
679=head1 AUTHOR
680
681Dave Rolsky E<lt>autarch@urth.orgE<gt>
682
683This is largely a reworking of code in Moose.pm originally written by
684Stevan Little and others.
685
686=head1 COPYRIGHT AND LICENSE
687
2840a3b2 688Copyright 2009 by Infinity Interactive, Inc.
e606ae5f 689
690L<http://www.iinteractive.com>
691
692This library is free software; you can redistribute it and/or modify
693it under the same terms as Perl itself.
694
695=cut