X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMoose%2FExporter.pm;h=961d172ce4186194db2c636d6cfe160673915bcd;hb=e2a758ad2cda3f25747bd9692a46c921cad45f34;hp=b07a4746aec4fa55667b1c950303f98a727c91f9;hpb=5116baeb0daf31309fee737a8b24a7e8cdd8c0a8;p=gitmo%2FMoose.git diff --git a/lib/Moose/Exporter.pm b/lib/Moose/Exporter.pm index b07a474..961d172 100644 --- a/lib/Moose/Exporter.pm +++ b/lib/Moose/Exporter.pm @@ -133,44 +133,71 @@ sub _make_exporter { ); } -{ - my $seen = {}; +sub _follow_also { + my $class = shift; + my $exporting_package = shift; + + _die_if_cycle_found_in_also_list_for_package($exporting_package); + + return uniq( _follow_also_real($exporting_package) ); +} + +sub _follow_also_real { + my $exporting_package = shift; + my @also = _also_list_for_package($exporting_package); - sub _follow_also { - my $class = shift; - my $exporting_package = shift; + return map { $_, _follow_also_real($_) } @also; +} - local %$seen = ( $exporting_package => 1 ); +sub _also_list_for_package { + my $package = shift; - return uniq( _follow_also_real($exporting_package) ); + if ( !exists $EXPORT_SPEC{$package} ) { + my $loaded = is_class_loaded($package); + + die "Package in also ($package) does not seem to " + . "use Moose::Exporter" + . ( $loaded ? "" : " (is it loaded?)" ); } - sub _follow_also_real { - my $exporting_package = shift; + my $also = $EXPORT_SPEC{$package}{also}; - if ( !exists $EXPORT_SPEC{$exporting_package} ) { - my $loaded = is_class_loaded($exporting_package); + return unless defined $also; - die "Package in also ($exporting_package) does not seem to " - . "use Moose::Exporter" - . ( $loaded ? "" : " (is it loaded?)" ); - } + return ref $also ? @$also : $also; +} - my $also = $EXPORT_SPEC{$exporting_package}{also}; +# this is no Tarjan algorithm, but for the list sizes expected, +# brute force will probably be fine (and more maintainable) +sub _die_if_cycle_found_in_also_list_for_package { + my $package = shift; + _die_if_also_list_cycles_back_to_existing_stack( + [ _also_list_for_package($package) ], + [$package], + ); +} - return unless defined $also; +sub _die_if_also_list_cycles_back_to_existing_stack { + my ( $also_list, $existing_stack ) = @_; - my @also = ref $also ? @{$also} : $also; + return unless @$also_list && @$existing_stack; - for my $package (@also) { - die - "Circular reference in 'also' parameter to Moose::Exporter between $exporting_package and $package" - if $seen->{$package}; + for my $also_member (@$also_list) { + for my $stack_member (@$existing_stack) { + next unless $also_member eq $stack_member; - $seen->{$package} = 1; + die + "Circular reference in 'also' parameter to Moose::Exporter between " + . join( + ', ', + @$existing_stack + ) . " and $also_member"; } - return @also, map { _follow_also_real($_) } @also; + _die_if_also_list_cycles_back_to_existing_stack( + [ _also_list_for_package($also_member) ], + [ $also_member, @$existing_stack ], + ); } } @@ -615,10 +642,11 @@ sub _apply_meta_traits { my $meta = $meta_lookup->($class); - my $type = ( split /::/, ref $meta )[-1] - or Moose->throw_error( - 'Cannot determine metaclass type for trait application . Meta isa ' - . ref $meta ); + my $type = $meta->isa('Moose::Meta::Role') ? 'Trait' + : $meta->isa('Class::MOP::Class') ? 'Class' + : Moose->throw_error('Cannot determine metaclass type for ' + . 'trait application. Meta isa ' + . ref $meta); my @resolved_traits = map { ref $_ @@ -737,7 +765,11 @@ sub _make_init_meta { return unless %new_style_roles || %old_style_roles || %base_class_roles; - return sub { }; + return sub { + shift; + my %opts = @_; + $meta_lookup->($opts{for_class}); + }; } sub import {