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