X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FMouse%2FMeta%2FRole.pm;h=709c3f957b1a36692e69820eb8a8735617797e8c;hb=29607c0291634fac077d6e1c75e1491ba455c010;hp=2008581dc10d2d8f013542b2ccb9ae9cb0bf56c2;hpb=07d18a6b15d6d937a78ecd2dd24f5375f0096766;p=gitmo%2FMouse.git diff --git a/lib/Mouse/Meta/Role.pm b/lib/Mouse/Meta/Role.pm index 2008581..709c3f9 100644 --- a/lib/Mouse/Meta/Role.pm +++ b/lib/Mouse/Meta/Role.pm @@ -2,6 +2,7 @@ package Mouse::Meta::Role; use strict; use warnings; use Carp 'confess'; +use Mouse::Util qw(version authority identifier); do { my %METACLASS_CACHE; @@ -42,6 +43,8 @@ sub add_required_methods { push @{$self->{required_methods}}, @methods; } + + sub add_attribute { my $self = shift; my $name = shift; @@ -61,12 +64,13 @@ sub get_method_list { no strict 'refs'; # Get all the CODE symbol table entries my @functions = - grep !/(?:has|with|around|before|after|blessed|extends|confess|excludes|meta|requires)/, + grep !/^(?:has|with|around|before|after|augment|inner|override|super|blessed|extends|confess|excludes|meta|requires)$/, grep { defined &{"${name}::$_"} } keys %{"${name}::"}; wantarray ? @functions : \@functions; } +# Moose uses Application::ToInstance, Application::ToClass, Application::ToRole sub apply { my $self = shift; my $selfname = $self->name; @@ -74,6 +78,10 @@ sub apply { my $classname = $class->name; my %args = @_; + if ($class->isa('Mouse::Object')) { + Carp::croak('Mouse does not support Application::ToInstance yet'); + } + if ($class->isa('Mouse::Meta::Class')) { for my $name (@{$self->{required_methods}}) { unless ($classname->can($name)) { @@ -87,16 +95,18 @@ sub apply { for my $name ($self->get_method_list) { next if $name eq 'meta'; - if ($classname->can($name)) { + my $class_function = "${classname}::${name}"; + my $role_function = "${selfname}::${name}"; + if (defined &$class_function) { # XXX what's Moose's behavior? #next; } else { - *{"${classname}::${name}"} = *{"${selfname}::${name}"}; + *{$class_function} = \&{$role_function}; } if ($args{alias} && $args{alias}->{$name}) { my $dstname = $args{alias}->{$name}; unless ($classname->can($dstname)) { - *{"${classname}::${dstname}"} = *{"${selfname}::${name}"}; + *{"${classname}::${dstname}"} = \&$role_function; } } } @@ -107,7 +117,19 @@ sub apply { for my $name ($self->get_attribute_list) { next if $class->has_attribute($name); my $spec = $self->get_attribute($name); - Mouse::Meta::Attribute->create($class, $name, %$spec); + + my $metaclass = 'Mouse::Meta::Attribute'; + if ( my $metaclass_name = $spec->{metaclass} ) { + my $new_class = Mouse::Util::resolve_metaclass_alias( + 'Attribute', + $metaclass_name + ); + if ( $metaclass ne $new_class ) { + $metaclass = $new_class; + } + } + + $metaclass->create($class, $name, %$spec); } } else { # apply role to role @@ -120,7 +142,7 @@ sub apply { } # XXX Room for speed improvement in role to role - for my $modifier_type (qw/before after around/) { + for my $modifier_type (qw/before after around override/) { my $add_method = "add_${modifier_type}_method_modifier"; my $modified = $self->{"${modifier_type}_method_modifiers"}; @@ -164,16 +186,18 @@ sub combine_apply { for my $name ($self->get_method_list) { next if $name eq 'meta'; - if ($classname->can($name)) { + my $class_function = "${classname}::${name}"; + my $role_function = "${selfname}::${name}"; + if (defined &$class_function) { # XXX what's Moose's behavior? #next; } else { - *{"${classname}::${name}"} = *{"${selfname}::${name}"}; + *$class_function = *$role_function; } if ($args{alias} && $args{alias}->{$name}) { my $dstname = $args{alias}->{$name}; unless ($classname->can($dstname)) { - *{"${classname}::${dstname}"} = *{"${selfname}::${name}"}; + *{"${classname}::${dstname}"} = \&$role_function; } } } @@ -188,7 +212,19 @@ sub combine_apply { for my $name ($self->get_attribute_list) { next if $class->has_attribute($name); my $spec = $self->get_attribute($name); - Mouse::Meta::Attribute->create($class, $name, %$spec); + + my $metaclass = 'Mouse::Meta::Attribute'; + if ( my $metaclass_name = $spec->{metaclass} ) { + my $new_class = Mouse::Util::resolve_metaclass_alias( + 'Attribute', + $metaclass_name + ); + if ( $metaclass ne $new_class ) { + $metaclass = $new_class; + } + } + + $metaclass->create($class, $name, %$spec); } } } else { @@ -205,7 +241,7 @@ sub combine_apply { } # XXX Room for speed improvement in role to role - for my $modifier_type (qw/before after around/) { + for my $modifier_type (qw/before after around override/) { my $add_method = "add_${modifier_type}_method_modifier"; for my $role_spec (@roles) { my $self = $role_spec->[0]->meta; @@ -221,17 +257,17 @@ sub combine_apply { # append roles my %role_apply_cache; - my @apply_roles; + my $apply_roles = $class->roles; for my $role_spec (@roles) { my $self = $role_spec->[0]->meta; - push @apply_roles, $self unless $role_apply_cache{$self}++; - for my $role ($self->roles) { - push @apply_roles, $role unless $role_apply_cache{$role}++; + push @$apply_roles, $self unless $role_apply_cache{$self}++; + for my $role (@{ $self->roles }) { + push @$apply_roles, $role unless $role_apply_cache{$role}++; } } } -for my $modifier_type (qw/before after around/) { +for my $modifier_type (qw/before after around override/) { no strict 'refs'; *{ __PACKAGE__ . '::' . "add_${modifier_type}_method_modifier" } = sub { my ($self, $method_name, $method) = @_; @@ -248,5 +284,23 @@ for my $modifier_type (qw/before after around/) { sub roles { $_[0]->{roles} } + +# This is currently not passing all the Moose tests. +sub does_role { + my ($self, $role_name) = @_; + + (defined $role_name) + || confess "You must supply a role name to look for"; + + # if we are it,.. then return true + return 1 if $role_name eq $self->name; + + for my $role (@{ $self->{roles} }) { + return 1 if $role->does_role($role_name); + } + return 0; +} + + 1;