Fix caller determination to work the same way as it did in old school
[gitmo/Moose.git] / lib / Moose / Exporter.pm
CommitLineData
5bd4db9b 1package Moose::Exporter;
2
3use strict;
4use warnings;
5
6use Class::MOP;
cd00320f 7use namespace::clean 0.08 ();
5bd4db9b 8use Sub::Exporter;
9
10
0338a411 11my %EXPORT_SPEC;
1a601f52 12
a5c426fc 13sub build_import_methods {
14 my $class = shift;
15 my %args = @_;
16
17 my $exporting_package = caller();
18
0338a411 19 $EXPORT_SPEC{$exporting_package} = \%args;
a5c426fc 20
1a601f52 21 my ( $exporter, $exported ) = $class->_build_exporter(
22 exporting_package => $exporting_package,
23 %args
24 );
a5c426fc 25
1a601f52 26 my $import = $class->_make_import_sub(
97a93056 27 $exporting_package, $args{init_meta_args},
1a601f52 28 $exporter
29 );
a5c426fc 30
1a601f52 31 my $unimport = $class->_make_unimport_sub($exported);
a5c426fc 32
33 no strict 'refs';
1a601f52 34 *{ $exporting_package . '::import' } = $import;
a5c426fc 35 *{ $exporting_package . '::unimport' } = $unimport;
36}
37
5bd4db9b 38my %EXPORTED;
a5c426fc 39sub _build_exporter {
5bd4db9b 40 my $class = shift;
41 my %args = @_;
42
a5c426fc 43 my $exporting_package = $args{exporting_package};
5bd4db9b 44
0338a411 45 my @exported_names;
5bd4db9b 46 my %exports;
97a93056 47 for my $name ( @{ $args{with_caller} } ) {
48 my $sub = do { no strict 'refs'; \&{ $exporting_package . '::' . $name } };
49
3492a4cd 50 # We need to set the package at import time, so that when
51 # package Foo imports has(), we capture "Foo" as the
52 # package. This lets other packages call Foo::has() and get
53 # the right package. This is done for backwards compatibility
54 # with existing production code, not because this is a good
55 # idea ;)
56 $exports{$name} = sub {
57 my $caller;
58
59 my $x = 0;
60 do
61 {
62 $caller = scalar caller($x++)
63 }
64 while ( $caller eq 'Sub::Exporter' );
65
66 Class::MOP::subname( $exporting_package . '::'
67 . $name => sub { $sub->( $caller, @_ ) } );
68 };
97a93056 69
70 push @exported_names, $name;
71 }
72
73 for my $name ( @{ $args{as_is} } ) {
5bd4db9b 74 my $sub;
97a93056 75
5bd4db9b 76 if ( ref $name ) {
77 $sub = $name;
78 $name = ( Class::MOP::get_code_info($name) )[1];
79 }
80 else {
a5c426fc 81 $sub = do { no strict 'refs'; \&{ $exporting_package . '::' . $name } };
5bd4db9b 82
0338a411 83 push @exported_names, $name;
5bd4db9b 84 }
85
86 $exports{$name} = sub { $sub };
87 }
88
0338a411 89 my $exporter = Sub::Exporter::build_exporter(
5bd4db9b 90 {
91 exports => \%exports,
92 groups => { default => [':all'] }
93 }
94 );
5bd4db9b 95
0338a411 96 return $exporter, \@exported_names;
5bd4db9b 97}
98
1a601f52 99sub _make_import_sub {
100 my $class = shift;
101 my $exporting_package = shift;
102 my $init_meta_args = shift;
103 my $exporter = shift;
104
105 return sub {
106 my $caller = Moose::Exporter->_get_caller(@_);
107
108 # this works because both pragmas set $^H (see perldoc perlvar)
109 # which affects the current compilation - i.e. the file who use'd
110 # us - which is why we don't need to do anything special to make
111 # it affect that file rather than this one (which is already compiled)
112
113 strict->import;
114 warnings->import;
115
116 # we should never export to main
117 if ( $caller eq 'main' ) {
118 warn
119 qq{$exporting_package does not export its sugar to the 'main' package.\n};
120 return;
121 }
122
123 if ( $exporting_package->can('_init_meta') ) {
124 $exporting_package->_init_meta(
125 for_class => $caller,
97a93056 126 %{ $init_meta_args || {} }
1a601f52 127 );
128 }
129
130 goto $exporter;
131 };
132}
133
134sub _get_caller {
135 # 1 extra level because it's called by import so there's a layer
136 # of indirection
137 my $offset = 1;
138
139 return
140 ( ref $_[1] && defined $_[1]->{into} ) ? $_[1]->{into}
141 : ( ref $_[1] && defined $_[1]->{into_level} )
142 ? caller( $offset + $_[1]->{into_level} )
143 : caller($offset);
144}
145
146sub _make_unimport_sub {
147 my $class = shift;
148 my $exported = shift;
149
150 # [12:24] <mst> yes. that's horrible. I know. but it should work.
151 #
152 # This will hopefully be replaced in the future once
153 # namespace::clean has an API for it.
154 return sub {
155 @_ = ( 'namespace::clean', @{$exported} );
156
157 goto &namespace::clean::import;
158 };
159}
160
5bd4db9b 1611;
2f29843c 162
163__END__
164
165=head1 NAME
166
167Moose::Exporter - make an import() and unimport() just like Moose.pm
168
169=head1 SYNOPSIS
170
171 package MyApp::Moose;
172
173 use strict;
174 use warnings;
175
176 use Moose ();
177 use Moose::Exporter;
178
179 Moose::Exporter->build_export_methods(
180 export => [ 'sugar1', 'sugar2', \&Some::Random::thing ],
181 init_meta_args => { metaclass_class => 'MyApp::Meta::Class' ],
182 );
183
184 # then later ...
185 package MyApp::User;
186
187 use MyApp::Moose;
188
189 has 'name';
190 sugar1 'do your thing';
191 thing;
192
193 no MyApp::Moose;
194
195=head1 DESCRIPTION
196
197This module encapsulates the logic to export sugar functions like
198C<Moose.pm>. It does this by building custom C<import> and C<unimport>
199methods for your module, based on a spec your provide.
200
201It also lets your "stack" Moose-alike modules so you can export
202Moose's sugar as well as your own, along with sugar from any random
203C<MooseX> module, as long as they all use C<Moose::Exporter>.
204
205=head1 METHODS
206
207This module provides exactly one public method:
208
209=head2 Moose::Exporter->build_import_methods(...)
210
211When you call this method, C<Moose::Exporter> build custom C<import>
212and C<unimport> methods for your module. The import method will export
213the functions you specify, and you can also tell it to export
214functions exported by some other module (like C<Moose.pm>).
215
216The C<unimport> method cleans the callers namespace of all the
217exported functions.
218
219This method accepts the following parameters:
220
221=over 4
222
97a93056 223=item * with_caller => [ ... ]
224
225This a list of function I<names only> to be exported wrapped and then
226exported. The wrapper will pass the name of the calling package as the
227first argument to the function. Many sugar functions need to know
228their caller so they can get the calling package's metaclass object.
229
230=item * as_is => [ ... ]
2f29843c 231
232This a list of function names or sub references to be exported
233as-is. You can identify a subroutine by reference, which is handy to
234re-export some other module's functions directly by reference
235(C<\&Some::Package::function>).
236
237=item * init_meta_args
238
239...
240
241=back
242
243=head1 AUTHOR
244
245Dave Rolsky E<lt>autarch@urth.orgE<gt>
246
247This is largely a reworking of code in Moose.pm originally written by
248Stevan Little and others.
249
250=head1 COPYRIGHT AND LICENSE
251
252Copyright 2008 by Infinity Interactive, Inc.
253
254L<http://www.iinteractive.com>
255
256This library is free software; you can redistribute it and/or modify
257it under the same terms as Perl itself.
258
259=cut