meta_lookup needs to propagate downwards, if unspecified
[gitmo/Moose.git] / lib / Moose / Exporter.pm
index 70bda3a..dcdef3c 100644 (file)
@@ -3,6 +3,7 @@ package Moose::Exporter;
 use strict;
 use warnings;
 
+use Class::Load qw(is_class_loaded);
 use Class::MOP;
 use List::MoreUtils qw( first_index uniq );
 use Moose::Util::MetaRole;
@@ -38,10 +39,10 @@ sub build_import_methods {
     my $is_reexport     = {};
 
     my $exports = $class->_make_sub_exporter_params(
-        [ @exports_from, $exporting_package ],
+        [ $exporting_package, @exports_from ],
         $export_recorder,
         $is_reexport,
-        $meta_lookup,
+        $args{meta_lookup}, # so that we don't pass through the default
     );
 
     my $exporter = $class->_make_exporter(
@@ -137,14 +138,14 @@ sub _make_exporter {
 
         local %$seen = ( $exporting_package => 1 );
 
-        return reverse uniq( _follow_also_real($exporting_package) );
+        return uniq( _follow_also_real($exporting_package) );
     }
 
     sub _follow_also_real {
         my $exporting_package = shift;
 
         if ( !exists $EXPORT_SPEC{$exporting_package} ) {
-            my $loaded = Class::MOP::is_class_loaded($exporting_package);
+            my $loaded = is_class_loaded($exporting_package);
 
             die "Package in also ($exporting_package) does not seem to "
                 . "use Moose::Exporter"
@@ -194,18 +195,25 @@ sub _parse_trait_aliases {
 }
 
 sub _make_sub_exporter_params {
-    my $class           = shift;
-    my $packages        = shift;
-    my $export_recorder = shift;
-    my $is_reexport     = shift;
-    my $meta_lookup     = shift;
+    my $class                = shift;
+    my $packages             = shift;
+    my $export_recorder      = shift;
+    my $is_reexport          = shift;
+    my $meta_lookup_override = shift;
 
     my %exports;
+    my $current_meta_lookup;
 
     for my $package ( @{$packages} ) {
         my $args = $EXPORT_SPEC{$package}
             or die "The $package package does not use Moose::Exporter\n";
 
+        $current_meta_lookup = $meta_lookup_override || $args->{meta_lookup};
+        $meta_lookup_override = $current_meta_lookup;
+
+        my $meta_lookup = $current_meta_lookup
+                       || sub { Class::MOP::class_of(shift) };
+
         for my $name ( @{ $args->{with_meta} } ) {
             my $sub = $class->_sub_from_package( $package, $name )
                 or next;
@@ -217,7 +225,7 @@ sub _make_sub_exporter_params {
                 $sub,
                 $export_recorder,
                 $meta_lookup,
-            );
+            ) unless exists $exports{$name};
         }
 
         for my $name ( @{ $args->{with_caller} } ) {
@@ -230,7 +238,7 @@ sub _make_sub_exporter_params {
                 $fq_name,
                 $sub,
                 $export_recorder,
-            );
+            ) unless exists $exports{$name};
         }
 
         my @extra_exports = $class->_parse_trait_aliases(
@@ -259,7 +267,8 @@ sub _make_sub_exporter_params {
 
             $export_recorder->{$sub} = 1;
 
-            $exports{$coderef_name} = sub {$sub};
+            $exports{$coderef_name} = sub { $sub }
+                unless exists $exports{$coderef_name};
         }
     }
 
@@ -783,11 +792,20 @@ when C<unimport> is called.
 
 =item * meta_lookup => sub { ... }
 
-This is a function which will be called to provide the metaclass to
-be operated upon by the exporter. This is an advanced feature
+This is a function which will be called to provide the metaclass
+to be operated upon by the exporter. This is an advanced feature
 intended for use by package generator modules in the vein of
-L<MooseX::Role::Parameterized> in order to simplify reusing sugar from other
-modules that use C<Moose::Exporter>.
+L<MooseX::Role::Parameterized> in order to simplify reusing sugar
+from other modules that use C<Moose::Exporter>. This function is
+used, for example, to select the metaclass to bind to functions
+that are exported using the C<with_meta> option.
+
+This function will receive one parameter: the class name into which
+the sugar is being exported. The default implementation is:
+
+    sub { Class::MOP::class_of(shift) }
+
+Accordingly, this function is expected to return a metaclass.
 
 =back