bump version to 0.97
[gitmo/Moose.git] / lib / Moose / Exporter.pm
index a3295e6..e7cdec8 100644 (file)
@@ -3,15 +3,20 @@ package Moose::Exporter;
 use strict;
 use warnings;
 
-our $VERSION   = '0.72';
+our $VERSION = '0.97';
+our $XS_VERSION = $VERSION;
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
 use Class::MOP;
 use List::MoreUtils qw( first_index uniq );
 use Moose::Util::MetaRole;
-use Sub::Exporter;
+use Sub::Exporter 0.980;
+use Sub::Name qw(subname);
 
+use XSLoader;
+
+XSLoader::load( 'Moose', $XS_VERSION );
 
 my %EXPORT_SPEC;
 
@@ -20,11 +25,10 @@ sub setup_import_methods {
 
     my $exporting_package = $args{exporting_package} ||= caller();
 
-    my ( $import, $unimport ) = $class->build_import_methods(%args);
-
-    no strict 'refs';
-    *{ $exporting_package . '::import' }   = $import;
-    *{ $exporting_package . '::unimport' } = $unimport;
+    $class->build_import_methods(
+        %args,
+        install => [qw(import unimport init_meta)]
+    );
 }
 
 sub build_import_methods {
@@ -34,13 +38,16 @@ sub build_import_methods {
 
     $EXPORT_SPEC{$exporting_package} = \%args;
 
-    my @exports_from = $class->_follow_also( $exporting_package );
+    my @exports_from = $class->_follow_also($exporting_package);
 
     my $export_recorder = {};
+    my $is_reexport     = {};
 
-    my ( $exports, $is_removable )
-        = $class->_make_sub_exporter_params(
-        [ @exports_from, $exporting_package ], $export_recorder );
+    my $exports = $class->_make_sub_exporter_params(
+        [ @exports_from, $exporting_package ],
+        $export_recorder,
+        $is_reexport,
+    );
 
     my $exporter = Sub::Exporter::build_exporter(
         {
@@ -49,16 +56,36 @@ sub build_import_methods {
         }
     );
 
-    # $args{_export_to_main} exists for backwards compat, because
-    # Moose::Util::TypeConstraints did export to main (unlike Moose &
-    # Moose::Role).
-    my $import = $class->_make_import_sub( $exporting_package, $exporter,
-        \@exports_from, $args{_export_to_main} );
+    my %methods;
+    $methods{import} = $class->_make_import_sub(
+        $exporting_package,
+        $exporter,
+        \@exports_from,
+        $is_reexport
+    );
+
+    $methods{unimport} = $class->_make_unimport_sub(
+        $exporting_package,
+        $exports,
+        $export_recorder,
+        $is_reexport
+    );
+
+    $methods{init_meta} = $class->_make_init_meta(
+        $exporting_package,
+        \%args
+    );
 
-    my $unimport = $class->_make_unimport_sub( $exporting_package, $exports,
-        $is_removable, $export_recorder );
+    my $package = Class::MOP::Package->initialize($exporting_package);
+    for my $to_install ( @{ $args{install} || [] } ) {
+        my $symbol = '&' . $to_install;
+        next
+            unless $methods{$to_install}
+                && !$package->has_package_symbol($symbol);
+        $package->add_package_symbol( $symbol, $methods{$to_install} );
+    }
 
-    return ( $import, $unimport )
+    return ( $methods{import}, $methods{unimport}, $methods{init_meta} );
 }
 
 {
@@ -76,8 +103,13 @@ sub build_import_methods {
     sub _follow_also_real {
         my $exporting_package = shift;
 
-        die "Package in also ($exporting_package) does not seem to use Moose::Exporter"
-            unless exists $EXPORT_SPEC{$exporting_package};
+        if ( !exists $EXPORT_SPEC{$exporting_package} ) {
+            my $loaded = Class::MOP::is_class_loaded($exporting_package);
+
+            die "Package in also ($exporting_package) does not seem to "
+                . "use Moose::Exporter"
+                . ( $loaded ? "" : " (is it loaded?)" );
+        }
 
         my $also = $EXPORT_SPEC{$exporting_package}{also};
 
@@ -85,9 +117,9 @@ sub build_import_methods {
 
         my @also = ref $also ? @{$also} : $also;
 
-        for my $package (@also)
-        {
-            die "Circular reference in also parameter to Moose::Exporter between $exporting_package and $package"
+        for my $package (@also) {
+            die
+                "Circular reference in 'also' parameter to Moose::Exporter between $exporting_package and $package"
                 if $seen->{$package};
 
             $seen->{$package} = 1;
@@ -98,22 +130,33 @@ sub build_import_methods {
 }
 
 sub _make_sub_exporter_params {
-    my $class             = shift;
-    my $packages          = shift;
-    my $export_recorder   = shift;
+    my $class           = shift;
+    my $packages        = shift;
+    my $export_recorder = shift;
+    my $is_reexport  = shift;
 
     my %exports;
-    my %is_removable;
 
     for my $package ( @{$packages} ) {
         my $args = $EXPORT_SPEC{$package}
             or die "The $package package does not use Moose::Exporter\n";
 
+        for my $name ( @{ $args->{with_meta} } ) {
+            my $sub = $class->_sub_from_package( $package, $name )
+                or next;
+
+            my $fq_name = $package . '::' . $name;
+
+            $exports{$name} = $class->_make_wrapped_sub_with_meta(
+                $fq_name,
+                $sub,
+                $export_recorder,
+            );
+        }
+
         for my $name ( @{ $args->{with_caller} } ) {
-            my $sub = do {
-                no strict 'refs';
-                \&{ $package . '::' . $name };
-            };
+            my $sub = $class->_sub_from_package( $package, $name )
+                or next;
 
             my $fq_name = $package . '::' . $name;
 
@@ -122,49 +165,53 @@ sub _make_sub_exporter_params {
                 $sub,
                 $export_recorder,
             );
-
-            $is_removable{$name} = 1;
         }
 
         for my $name ( @{ $args->{as_is} } ) {
-            my $sub;
+            my ( $sub, $coderef_name );
 
             if ( ref $name ) {
-                $sub  = $name;
-
-                # Even though Moose re-exports things from Carp &
-                # Scalar::Util, we don't want to remove those at
-                # unimport time, because the importing package may
-                # have imported them explicitly ala
-                #
-                # use Carp qw( confess );
-                #
-                # This is a hack. Since we can't know whether they
-                # really want to keep these subs or not, we err on the
-                # safe side and leave them in.
+                $sub = $name;
+
                 my $coderef_pkg;
-                ( $coderef_pkg, $name ) = Class::MOP::get_code_info($name);
+                ( $coderef_pkg, $coderef_name )
+                    = Class::MOP::get_code_info($name);
 
-                $is_removable{$name} = $coderef_pkg eq $package ? 1 : 0;
+                if ( $coderef_pkg ne $package ) {
+                    $is_reexport->{$coderef_name} = 1;
+                }
             }
             else {
-                $sub = do {
-                    no strict 'refs';
-                    \&{ $package . '::' . $name };
-                };
+                $sub = $class->_sub_from_package( $package, $name )
+                    or next;
 
-                $is_removable{$name} = 1;
+                $coderef_name = $name;
             }
 
-            $class->_make_prototyped_sub($sub);
-
             $export_recorder->{$sub} = 1;
 
-            $exports{$name} = sub {$sub};
+            $exports{$coderef_name} = sub {$sub};
         }
     }
 
-    return ( \%exports, \%is_removable );
+    return \%exports;
+}
+
+sub _sub_from_package {
+    my $sclass  = shift;
+    my $package = shift;
+    my $name    = shift;
+
+    my $sub = do {
+        no strict 'refs';
+        \&{ $package . '::' . $name };
+    };
+
+    return $sub if defined &$sub;
+
+    Carp::cluck "Trying to export undefined sub ${package}::${name}";
+
+    return;
 }
 
 our $CALLER;
@@ -184,9 +231,9 @@ sub _make_wrapped_sub {
     return sub {
         my $caller = $CALLER;
 
-        my $wrapper = $self->_make_wrapper($caller, $sub, $fq_name);
+        my $wrapper = $self->_curry_wrapper( $sub, $fq_name, $caller );
 
-        my $sub = Class::MOP::subname($fq_name => $wrapper);
+        my $sub = subname( $fq_name => $wrapper );
 
         $export_recorder->{$sub} = 1;
 
@@ -194,34 +241,63 @@ sub _make_wrapped_sub {
     };
 }
 
-sub _make_prototyped_sub {
-    shift;
-    my $sub = shift;
-
-    # If I use Scalar::Util::set_prototype, this will forever be bound to XS.
-    # And it's hard to use anyway (it requires a BLOCK or a sub{} declaration
-    # as its first argument)
-    if (my $proto = prototype $sub) {
-        $sub = eval "sub ($proto) { \$sub->(\@_) }";
-        Carp::confess if $@;
+sub _make_wrapped_sub_with_meta {
+    my $self            = shift;
+    my $fq_name         = shift;
+    my $sub             = shift;
+    my $export_recorder = shift;
+
+    return sub {
+        my $caller = $CALLER;
+
+        my $wrapper = $self->_late_curry_wrapper(
+            $sub, $fq_name,
+            sub { Class::MOP::class_of(shift) } => $caller
+        );
+
+        my $sub = subname( $fq_name => $wrapper );
+
+        $export_recorder->{$sub} = 1;
+
+        return $sub;
+    };
+}
+
+sub _curry_wrapper {
+    my $class   = shift;
+    my $sub     = shift;
+    my $fq_name = shift;
+    my @extra   = @_;
+
+    my $wrapper = sub { $sub->( @extra, @_ ) };
+    if ( my $proto = prototype $sub ) {
+
+        # XXX - Perl's prototype sucks. Use & to make set_prototype
+        # ignore the fact that we're passing "private variables"
+        &Scalar::Util::set_prototype( $wrapper, $proto );
     }
-    return $sub;
+    return $wrapper;
 }
 
-sub _make_wrapper {
+sub _late_curry_wrapper {
     my $class   = shift;
-    my $caller  = shift;
     my $sub     = shift;
     my $fq_name = shift;
+    my $extra   = shift;
+    my @ex_args = @_;
+
+    my $wrapper = sub {
 
-    # XXX optimization: since we're building a new sub anyways, we
-    # unroll _make_prototyped_sub here
-    my $wrapper;
-    if (my $proto = prototype $sub) {
-        $wrapper = eval "sub ($proto) { \$sub->(\$caller, \@_) }";
-        Carp::confess if $@;
-    } else {
-        $wrapper = sub { $sub->($caller, @_) };
+        # resolve curried arguments at runtime via this closure
+        my @curry = ( $extra->(@ex_args) );
+        return $sub->( @curry, @_ );
+    };
+
+    if ( my $proto = prototype $sub ) {
+
+        # XXX - Perl's prototype sucks. Use & to make set_prototype
+        # ignore the fact that we're passing "private variables"
+        &Scalar::Util::set_prototype( $wrapper, $proto );
     }
     return $wrapper;
 }
@@ -231,7 +307,7 @@ sub _make_import_sub {
     my $exporting_package = shift;
     my $exporter          = shift;
     my $exports_from      = shift;
-    my $export_to_main    = shift;
+    my $is_reexport    = shift;
 
     return sub {
 
@@ -246,6 +322,12 @@ sub _make_import_sub {
         my $traits;
         ( $traits, @_ ) = _strip_traits(@_);
 
+        my $metaclass;
+        ( $metaclass, @_ ) = _strip_metaclass(@_);
+        $metaclass
+            = Moose::Util::resolve_metaclass_alias( 'Class' => $metaclass )
+            if defined $metaclass && length $metaclass;
+
         # Normally we could look at $_[0], but in some weird cases
         # (involving goto &Moose::import), $_[0] ends as something
         # else (like Squirrel).
@@ -262,24 +344,19 @@ sub _make_import_sub {
         strict->import;
         warnings->import;
 
-        # we should never export to main
-        if ( $CALLER eq 'main' && !$export_to_main ) {
-            warn
-                qq{$class does not export its sugar to the 'main' package.\n};
-            return;
-        }
-
         my $did_init_meta;
         for my $c ( grep { $_->can('init_meta') } $class, @{$exports_from} ) {
+
             # init_meta can apply a role, which when loaded uses
             # Moose::Exporter, which in turn sets $CALLER, so we need
             # to protect against that.
             local $CALLER = $CALLER;
-            $c->init_meta( for_class => $CALLER );
+            $c->init_meta( for_class => $CALLER, metaclass => $metaclass );
             $did_init_meta = 1;
         }
 
         if ( $did_init_meta && @{$traits} ) {
+
             # The traits will use Moose::Role, which in turn uses
             # Moose::Exporter, which in turn sets $CALLER, so we need
             # to protect against that.
@@ -293,11 +370,25 @@ sub _make_import_sub {
             );
         }
 
-        goto $exporter;
+        my ( undef, @args ) = @_;
+        my $extra = shift @args if ref $args[0] eq 'HASH';
+
+        $extra ||= {};
+        if ( !$extra->{into} ) {
+            $extra->{into_level} ||= 0;
+            $extra->{into_level}++;
+        }
+
+        $class->$exporter( $extra, @args );
+
+        for my $name ( keys %{$is_reexport} ) {
+            no strict 'refs';
+            no warnings 'once';
+            _flag_as_reexport( \*{ join q{::}, $CALLER, $name } );
+        }
     };
 }
 
-
 sub _strip_traits {
     my $idx = first_index { $_ eq '-traits' } @_;
 
@@ -307,36 +398,57 @@ sub _strip_traits {
 
     splice @_, $idx, 2;
 
-    $traits = [ $traits ] unless ref $traits;
+    $traits = [$traits] unless ref $traits;
 
     return ( $traits, @_ );
 }
 
+sub _strip_metaclass {
+    my $idx = first_index { $_ eq '-metaclass' } @_;
+
+    return ( undef, @_ ) unless $idx >= 0 && $#_ >= $idx + 1;
+
+    my $metaclass = $_[ $idx + 1 ];
+
+    splice @_, $idx, 2;
+
+    return ( $metaclass, @_ );
+}
+
 sub _apply_meta_traits {
     my ( $class, $traits ) = @_;
 
     return unless @{$traits};
 
-    my $meta = $class->meta();
+    my $meta = Class::MOP::class_of($class);
 
     my $type = ( split /::/, ref $meta )[-1]
         or Moose->throw_error(
         'Cannot determine metaclass type for trait application . Meta isa '
-        . ref $meta );
+            . ref $meta );
 
-    my @resolved_traits
-        = map { Moose::Util::resolve_metatrait_alias( $type => $_ ) }
-        @$traits;
+    my @resolved_traits = map {
+        ref $_
+            ? $_
+            : Moose::Util::resolve_metatrait_alias( $type => $_ )
+    } @$traits;
 
     return unless @resolved_traits;
 
-    Moose::Util::MetaRole::apply_metaclass_roles(
-        for_class       => $class,
-        metaclass_roles => \@resolved_traits,
-    );
+    my %args = ( for => $class );
+
+    if ( $meta->isa('Moose::Meta::Role') ) {
+        $args{role_metaroles} = { role => \@resolved_traits };
+    }
+    else {
+        $args{class_metaroles} = { class => \@resolved_traits };
+    }
+
+    Moose::Util::MetaRole::apply_metaroles(%args);
 }
 
 sub _get_caller {
+
     # 1 extra level because it's called by import so there's a layer
     # of indirection
     my $offset = 1;
@@ -352,16 +464,16 @@ sub _make_unimport_sub {
     shift;
     my $exporting_package = shift;
     my $exports           = shift;
-    my $is_removable      = shift;
     my $export_recorder   = shift;
+    my $is_reexport    = shift;
 
     return sub {
         my $caller = scalar caller();
         Moose::Exporter->_remove_keywords(
             $caller,
             [ keys %{$exports} ],
-            $is_removable,
             $export_recorder,
+            $is_reexport,
         );
     };
 }
@@ -370,26 +482,91 @@ sub _remove_keywords {
     shift;
     my $package          = shift;
     my $keywords         = shift;
-    my $is_removable     = shift;
     my $recorded_exports = shift;
+    my $is_reexport   = shift;
 
     no strict 'refs';
 
-    foreach my $name ( @{ $keywords } ) {
-        next unless $is_removable->{$name};
-
+    foreach my $name ( @{$keywords} ) {
         if ( defined &{ $package . '::' . $name } ) {
             my $sub = \&{ $package . '::' . $name };
 
             # make sure it is from us
             next unless $recorded_exports->{$sub};
 
+            if ( $is_reexport->{$name} ) {
+                no strict 'refs';
+                next
+                    unless _export_is_flagged(
+                            \*{ join q{::} => $package, $name } );
+            }
+
             # and if it is from us, then undef the slot
             delete ${ $package . '::' }{$name};
         }
     }
 }
 
+sub _make_init_meta {
+    shift;
+    my $class = shift;
+    my $args  = shift;
+
+    my %old_style_roles;
+    for my $role (
+        map {"${_}_roles"}
+        qw(
+        metaclass
+        attribute_metaclass
+        method_metaclass
+        wrapped_method_metaclass
+        instance_metaclass
+        constructor_class
+        destructor_class
+        error_class
+        )
+        ) {
+        $old_style_roles{$role} = $args->{$role}
+            if exists $args->{$role};
+    }
+
+    my %base_class_roles;
+    %base_class_roles = ( roles => $args->{base_class_roles} )
+        if exists $args->{base_class_roles};
+
+    my %new_style_roles = map { $_ => $args->{$_} }
+        grep { exists $args->{$_} } qw( class_metaroles role_metaroles );
+
+    return unless %new_style_roles || %old_style_roles || %base_class_roles;
+
+    return sub {
+        shift;
+        my %options = @_;
+
+        return unless Class::MOP::class_of( $options{for_class} );
+
+        Moose::Util::MetaRole::apply_metaroles(
+            for => $options{for_class},
+            %new_style_roles,
+            %old_style_roles,
+        );
+
+        Moose::Util::MetaRole::apply_base_class_roles(
+            for_class => $options{for_class},
+            %base_class_roles,
+            )
+            if Class::MOP::class_of( $options{for_class} )
+                ->isa('Moose::Meta::Class');
+
+        return Class::MOP::class_of( $options{for_class} );
+    };
+}
+
+sub import {
+    strict->import;
+    warnings->import;
+}
+
 1;
 
 __END__
@@ -402,21 +579,19 @@ Moose::Exporter - make an import() and unimport() just like Moose.pm
 
   package MyApp::Moose;
 
-  use strict;
-  use warnings;
-
   use Moose ();
   use Moose::Exporter;
 
   Moose::Exporter->setup_import_methods(
-      with_caller => [ 'has_rw', 'sugar2' ],
-      as_is       => [ 'sugar3', \&Some::Random::thing ],
-      also        => 'Moose',
+      with_meta => [ 'has_rw', 'sugar2' ],
+      as_is     => [ 'sugar3', \&Some::Random::thing ],
+      also      => 'Moose',
   );
 
   sub has_rw {
-      my ($caller, $name, %options) = @_;
-      Class::MOP::Class->initialize($caller)->add_attribute($name,
+      my ( $meta, $name, %options ) = @_;
+      $meta->add_attribute(
+          $name,
           is => 'rw',
           %options,
       );
@@ -435,57 +610,77 @@ Moose::Exporter - make an import() and unimport() just like Moose.pm
 
 =head1 DESCRIPTION
 
-This module encapsulates the logic to export sugar functions like
-C<Moose.pm>. It does this by building custom C<import> and C<unimport>
-methods for your module, based on a spec your provide.
+This module encapsulates the exporting of sugar functions in a
+C<Moose.pm>-like manner. It does this by building custom C<import>,
+C<unimport>, and C<init_meta> methods for your module, based on a spec you
+provide.
+
+It also lets you "stack" Moose-alike modules so you can export Moose's sugar
+as well as your own, along with sugar from any random C<MooseX> module, as
+long as they all use C<Moose::Exporter>. This feature exists to let you bundle
+a set of MooseX modules into a policy module that developers can use directly
+instead of using Moose itself.
 
-It also lets your "stack" Moose-alike modules so you can export
-Moose's sugar as well as your own, along with sugar from any random
-C<MooseX> module, as long as they all use C<Moose::Exporter>.
+To simplify writing exporter modules, C<Moose::Exporter> also imports
+C<strict> and C<warnings> into your exporter module, as well as into
+modules that use it.
 
 =head1 METHODS
 
 This module provides two public methods:
 
-=head2 Moose::Exporter->setup_import_methods(...)
+=over 4
+
+=item  B<< Moose::Exporter->setup_import_methods(...) >>
 
-When you call this method, C<Moose::Exporter> build custom C<import>
-and C<unimport> methods for your module. The import method will export
-the functions you specify, and you can also tell it to export
-functions exported by some other module (like C<Moose.pm>).
+When you call this method, C<Moose::Exporter> builds custom C<import>,
+C<unimport>, and C<init_meta> methods for your module. The C<import> method
+will export the functions you specify, and can also re-export functions
+exported by some other module (like C<Moose.pm>).
 
-The C<unimport> method cleans the callers namespace of all the
-exported functions.
+The C<unimport> method cleans the caller's namespace of all the exported
+functions. This includes any functions you re-export from other
+packages. However, if the consumer of your package also imports those
+functions from the original package, they will I<not> be cleaned.
+
+If you pass any parameters for L<Moose::Util::MetaRole>, this method will
+generate an C<init_meta> for you as well (see below for details). This
+C<init_meta> will call C<Moose::Util::MetaRole::apply_metaclass_roles> and
+C<Moose::Util::MetaRole::apply_base_class_roles> as needed.
+
+Note that if any of these methods already exist, they will not be
+overridden, you will have to use C<build_import_methods> to get the
+coderef that would be installed.
 
 This method accepts the following parameters:
 
-=over 4
+=over 8
+
+=item * with_meta => [ ... ]
 
-=item * with_caller => [ ... ]
+This list of function I<names only> will be wrapped and then exported. The
+wrapper will pass the metaclass object for the caller as its first argument.
 
-This a list of function I<names only> to be exported wrapped and then
-exported. The wrapper will pass the name of the calling package as the
-first argument to the function. Many sugar functions need to know
-their caller so they can get the calling package's metaclass object.
+Many sugar functions will need to use this metaclass object to do something to
+the calling package.
 
 =item * as_is => [ ... ]
 
-This a list of function names or sub references to be exported
-as-is. You can identify a subroutine by reference, which is handy to
-re-export some other module's functions directly by reference
-(C<\&Some::Package::function>).
+This list of function names or sub references will be exported as-is. You can
+identify a subroutine by reference, which is handy to re-export some other
+module's functions directly by reference (C<\&Some::Package::function>).
 
-If you do export some other packages function, this function will
-never be removed by the C<unimport> method. The reason for this is we
-cannot know if the caller I<also> explicitly imported the sub
-themselves, and therefore wants to keep it.
+If you do export some other package's function, this function will never be
+removed by the C<unimport> method. The reason for this is we cannot know if
+the caller I<also> explicitly imported the sub themselves, and therefore wants
+to keep it.
 
 =item * also => $name or \@names
 
 This is a list of modules which contain functions that the caller
 wants to export. These modules must also use C<Moose::Exporter>. The
 most common use case will be to export the functions from C<Moose.pm>.
-Functions specified by C<with_caller> or C<as_is> take precedence over
+Functions specified by C<with_meta> or C<as_is> take precedence over
 functions exported by modules specified by C<also>, so that a module
 can selectively override functions exported by another module.
 
@@ -494,19 +689,36 @@ when C<unimport> is called.
 
 =back
 
-=head2 Moose::Exporter->build_import_methods(...)
+You can also provide parameters for C<Moose::Util::MetaRole::apply_metaroles>
+and C<Moose::Util::MetaRole::base_class_roles>. Specifically, valid parameters
+are "class_metaroles", "role_metaroles", and "base_object_roles".
 
-Returns two code refs, one for import and one for unimport.
+=item B<< Moose::Exporter->build_import_methods(...) >>
+
+Returns two or three code refs, one for C<import>, one for
+C<unimport>, and optionally one for C<init_meta>, if the appropriate
+options are passed in.
+
+Accepts the additional C<install> option, which accepts an arrayref of method
+names to install into your exporting package. The valid options are C<import>,
+C<unimport>, and C<init_meta>. Calling C<setup_import_methods> is equivalent
+to calling C<build_import_methods> with C<< install => [qw(import unimport
+init_meta)] >> except that it doesn't also return the methods.
 
 Used by C<setup_import_methods>.
 
+=back
+
 =head1 IMPORTING AND init_meta
 
-If you want to set an alternative base object class or metaclass
-class, simply define an C<init_meta> method in your class. The
-C<import> method that C<Moose::Exporter> generates for you will call
-this method (if it exists). It will always pass the caller to this
-method via the C<for_class> parameter.
+If you want to set an alternative base object class or metaclass class, see
+above for details on how this module can call L<Moose::Util::MetaRole> for
+you.
+
+If you want to do something that is not supported by this module, simply
+define an C<init_meta> method in your class. The C<import> method that
+C<Moose::Exporter> generates for you will call this method (if it exists). It
+will always pass the caller to this method via the C<for_class> parameter.
 
 Most of the time, your C<init_meta> method will probably just call C<<
 Moose->init_meta >> to do the real work:
@@ -516,6 +728,35 @@ Moose->init_meta >> to do the real work:
       return Moose->init_meta( @_, metaclass => 'My::Metaclass' );
   }
 
+Keep in mind that C<build_import_methods> will return an C<init_meta>
+method for you, which you can also call from within your custom
+C<init_meta>:
+
+  my ( $import, $unimport, $init_meta ) =
+      Moose::Exporter->build_import_methods( ... );
+
+  sub import {
+     my $class = shift;
+
+     ...
+
+     $class->$import(...);
+
+     ...
+  }
+
+  sub unimport { goto &$unimport }
+
+  sub init_meta {
+     my $class = shift;
+
+     ...
+
+     $class->$init_meta(...);
+
+     ...
+  }
+
 =head1 METACLASS TRAITS
 
 The C<import> method generated by C<Moose::Exporter> will allow the
@@ -530,6 +771,10 @@ These traits will be applied to the caller's metaclass
 instance. Providing traits for an exporting class that does not create
 a metaclass for the caller is an error.
 
+=head1 BUGS
+
+See L<Moose/BUGS> for details on reporting bugs.
+
 =head1 AUTHOR
 
 Dave Rolsky E<lt>autarch@urth.orgE<gt>