X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=gitmo%2FMouse.git;a=blobdiff_plain;f=lib%2FMouse%2FUtil%2FMetaRole.pm;h=668b35ce3efd9a1847d166de0d1acd70d38eb663;hp=fe68cbeb41ddf173305e284e61db44f313716d53;hb=d9659f80a6e4f20234968fcc003570c0da6b6ff1;hpb=a17f63138ec09db5e362700f2ac72da67f104786 diff --git a/lib/Mouse/Util/MetaRole.pm b/lib/Mouse/Util/MetaRole.pm index fe68cbe..668b35c 100644 --- a/lib/Mouse/Util/MetaRole.pm +++ b/lib/Mouse/Util/MetaRole.pm @@ -1,35 +1,43 @@ package Mouse::Util::MetaRole; use Mouse::Util; # enables strict and warnings -our @Classes = qw(constructor_class destructor_class); +my @MetaClassTypes = qw( + metaclass + attribute_metaclass + method_metaclass + constructor_class + destructor_class +); +# In Mouse::Exporter::do_import(): +# apply_metaclass_roles(for_class => $class, metaclass_roles => \@traits) sub apply_metaclass_roles { my %options = @_; my $for = Scalar::Util::blessed($options{for_class}) ? $options{for_class} - : Mouse::Util::class_of($options{for_class}); + : Mouse::Util::get_metaclass_by_name($options{for_class}); - my %old_classes = map { $for->can($_) ? ($_ => $for->$_) : () } - @Classes; + my $new_metaclass = _make_new_class( ref $for, + $options{metaclass_roles}, + $options{metaclass} ? [$options{metaclass}] : undef, + ); - my $meta = _make_new_metaclass( $for, \%options ); + my @metaclass_map; - for my $c ( grep { $meta->can($_) } @Classes ) { - if ( $options{ $c . '_roles' } ) { - my $class = _make_new_class( - $meta->$c(), - $options{ $c . '_roles' } - ); + foreach my $mc_type(@MetaClassTypes){ + next if !$for->can($mc_type); - $meta->$c($class); + if(my $roles = $options{ $mc_type . '_roles' }){ + push @metaclass_map, + ($mc_type => _make_new_class($for->$mc_type(), $roles)); } - elsif($meta->$c ne $old_classes{$c}){ - $meta->$c( $old_classes{$c} ); + elsif(my $mc = $options{$mc_type}){ + push @metaclass_map, ($mc_type => $mc); } } - return $meta; + return $new_metaclass->reinitialize( $for, @metaclass_map ); } sub apply_base_class_roles { @@ -50,40 +58,17 @@ sub apply_base_class_roles { return; } - -my @Metaclasses = qw( - metaclass - attribute_metaclass - method_metaclass -); - -sub _make_new_metaclass { - my($for, $options) = @_; - - return $for - if !grep { exists $options->{ $_ . '_roles' } } @Metaclasses; - - my $new_metaclass - = _make_new_class( ref $for, $options->{metaclass_roles} ); - - # This could get called for a Mouse::Meta::Role as well as a Mouse::Meta::Class - my %classes = map { - $_ => _make_new_class( $for->$_(), $options->{ $_ . '_roles' } ) - } grep { $for->can($_) } @Metaclasses; - - return $new_metaclass->reinitialize( $for, %classes ); -} - - sub _make_new_class { my($existing_class, $roles, $superclasses) = @_; - return $existing_class if !$roles; + if(!$superclasses){ + return $existing_class if !$roles; - my $meta = Mouse::Meta::Class->initialize($existing_class); + my $meta = Mouse::Meta::Class->initialize($existing_class); - return $existing_class - if !grep { !ref($_) && !$meta->does_role($_) } @{$roles}; + return $existing_class + if !grep { !ref($_) && !$meta->does_role($_) } @{$roles}; + } return Mouse::Meta::Class->create_anon_class( superclasses => $superclasses ? $superclasses : [$existing_class],