Support is => 'bare' for compatibility
[gitmo/Mouse.git] / lib / Mouse / Meta / Role.pm
index e82690d..2ea38e2 100644 (file)
@@ -2,7 +2,9 @@ package Mouse::Meta::Role;
 use strict;
 use warnings;
 use Carp 'confess';
-use Mouse::Util;
+
+use Mouse::Meta::Attribute;
+use Mouse::Util qw(version authority identifier);
 
 do {
     my %METACLASS_CACHE;
@@ -43,11 +45,13 @@ sub add_required_methods {
     push @{$self->{required_methods}}, @methods;
 }
 
+
+
 sub add_attribute {
     my $self = shift;
     my $name = shift;
     my $spec = shift;
-    $self->{attributes}->{$name} = $spec;
+    $self->{attributes}->{$name} = Mouse::Meta::Attribute->new($name, %$spec);
 }
 
 sub has_attribute { exists $_[0]->{attributes}->{$_[1]}  }
@@ -62,12 +66,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;
@@ -75,6 +80,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)) {
@@ -88,16 +97,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;
                 }
             }
         }
@@ -133,7 +144,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"};
 
@@ -177,16 +188,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;
                     }
                 }
             }
@@ -230,7 +243,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;
@@ -246,17 +259,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) = @_;
@@ -273,5 +286,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;