Fix typo in comment
[gitmo/Moose.git] / lib / Moose / Meta / Role.pm
index 640cb84..01689cc 100644 (file)
@@ -5,10 +5,10 @@ use strict;
 use warnings;
 use metaclass;
 
-use Carp         'confess';
 use Scalar::Util 'blessed';
 
-our $VERSION   = '0.56';
+our $VERSION   = '0.59';
+$VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
 use Moose::Meta::Class;
@@ -121,6 +121,8 @@ foreach my $action (
 sub add_attribute {
     my $self = shift;
     my $name = shift;
+    (defined $name && $name)
+        || Moose->throw_error("You must provide a name for the attribute");
     my $attr_desc;
     if (scalar @_ == 1 && ref($_[0]) eq 'HASH') {
         $attr_desc = $_[0];
@@ -214,8 +216,8 @@ $META->add_attribute('override_method_modifiers' => (
 sub add_override_method_modifier {
     my ($self, $method_name, $method) = @_;
     (!$self->has_method($method_name))
-        || confess "Cannot add an override of method '$method_name' " .
-                   "because there is a local version of '$method_name'";
+        || Moose->throw_error("Cannot add an override of method '$method_name' " .
+                   "because there is a local version of '$method_name'");
     $self->get_override_method_modifiers_map->{$method_name} = $method;
 }
 
@@ -240,6 +242,14 @@ sub get_method_modifier_list {
     keys %{$self->$accessor};
 }
 
+sub reset_package_cache_flag  { (shift)->{'_package_cache_flag'} = undef }
+sub update_package_cache_flag {
+    my $self = shift;
+    $self->{'_package_cache_flag'} = Class::MOP::check_package_cache_flag($self->name);
+}
+
+
+
 ## ------------------------------------------------------------------
 ## subroles
 
@@ -251,8 +261,9 @@ __PACKAGE__->meta->add_attribute('roles' => (
 sub add_role {
     my ($self, $role) = @_;
     (blessed($role) && $role->isa('Moose::Meta::Role'))
-        || confess "Roles must be instances of Moose::Meta::Role";
+        || Moose->throw_error("Roles must be instances of Moose::Meta::Role");
     push @{$self->get_roles} => $role;
+    $self->reset_package_cache_flag;
 }
 
 sub calculate_all_roles {
@@ -268,7 +279,7 @@ sub calculate_all_roles {
 sub does_role {
     my ($self, $role_name) = @_;
     (defined $role_name)
-        || confess "You must supply a role name to look for";
+        || Moose->throw_error("You must supply a role name to look for");
     # if we are it,.. then return true
     return 1 if $role_name eq $self->name;
     # otherwise.. check our children
@@ -285,7 +296,16 @@ sub method_metaclass { 'Moose::Meta::Role::Method' }
 
 sub get_method_map {
     my $self = shift;
-    my $map  = {};
+
+    my $current = Class::MOP::check_package_cache_flag($self->name);
+
+    if (defined $self->{'_package_cache_flag'} && $self->{'_package_cache_flag'} == $current) {
+        return $self->{'methods'} ||= {};
+    }
+
+    $self->{_package_cache_flag} = $current;
+
+    my $map  = $self->{'methods'} ||= {};
 
     my $role_name        = $self->name;
     my $method_metaclass = $self->method_metaclass;
@@ -295,6 +315,10 @@ sub get_method_map {
     foreach my $symbol (keys %all_code) {
         my $code = $all_code{$symbol};
 
+        next if exists  $map->{$symbol} &&
+                defined $map->{$symbol} &&
+                        $map->{$symbol}->body == $code;
+
         my ($pkg, $name) = Class::MOP::get_code_info($code);
 
         if ($pkg->can('meta')
@@ -305,7 +329,7 @@ sub get_method_map {
             # loudly (in the case of Curses.pm) so we
             # just be a little overly cautious here.
             # - SL
-            && eval { no warnings; blessed($pkg->meta) }
+            && eval { no warnings; blessed($pkg->meta) } # FIXME calls meta
             && $pkg->meta->isa('Moose::Meta::Role')) {
             my $role = $pkg->meta->name;
             next unless $self->does_role($role);
@@ -344,26 +368,64 @@ sub has_method {
     exists $self->get_method_map->{$name} ? 1 : 0
 }
 
-sub find_method_by_name { (shift)->get_method(@_) }
+# FIXME this is copypasated from Class::MOP::Class
+# refactor to inherit from some common base
+sub wrap_method_body {
+    my ( $self, %args ) = @_;
 
-sub get_method_list {
-    my $self = shift;
-    grep { !/^meta$/ } keys %{$self->get_method_map};
+    ('CODE' eq ref $args{body})
+        || Moose->throw_error("Your code block must be a CODE reference");
+
+    $self->method_metaclass->wrap(
+        package_name => $self->name,
+        %args,
+    );
 }
 
-sub alias_method {
+sub add_method {
     my ($self, $method_name, $method) = @_;
     (defined $method_name && $method_name)
-        || confess "You must define a method name";
+    || Moose->throw_error("You must define a method name");
+
+    my $body;
+    if (blessed($method)) {
+        $body = $method->body;
+        if ($method->package_name ne $self->name) {
+            $method = $method->clone(
+                package_name => $self->name,
+                name         => $method_name            
+            ) if $method->can('clone');
+        }
+    }
+    else {
+        $body = $method;
+        $method = $self->wrap_method_body( body => $body, name => $method_name );
+    }
+
+    $method->attach_to_class($self);
 
-    my $body = (blessed($method) ? $method->body : $method);
-    ('CODE' eq ref($body))
-        || confess "Your code block must be a CODE reference";
+    $self->get_method_map->{$method_name} = $method;
 
+    my $full_method_name = ($self->name . '::' . $method_name);
     $self->add_package_symbol(
         { sigil => '&', type => 'CODE', name => $method_name },
-        $body
+        Class::MOP::subname($full_method_name => $body)
     );
+
+    $self->update_package_cache_flag; # still valid, since we just added the method to the map, and if it was invalid before that then get_method_map updated it
+}
+
+sub find_method_by_name { (shift)->get_method(@_) }
+
+sub get_method_list {
+    my $self = shift;
+    grep { !/^meta$/ } keys %{$self->get_method_map};
+}
+
+sub alias_method {
+    my $self = shift;
+
+    $self->add_method(@_);
 }
 
 ## ------------------------------------------------------------------
@@ -374,7 +436,7 @@ sub apply {
     my ($self, $other, @args) = @_;
 
     (blessed($other))
-        || confess "You must pass in an blessed instance";
+        || Moose->throw_error("You must pass in an blessed instance");
         
     if ($other->isa('Moose::Meta::Role')) {
         require Moose::Meta::Role::Application::ToRole;
@@ -560,6 +622,8 @@ probably not that much really).
 
 =item B<apply>
 
+=item B<apply_to_metaclass_instance>
+
 =item B<combine>
 
 =back
@@ -608,6 +672,10 @@ probably not that much really).
 
 =item B<has_method>
 
+=item B<add_method>
+
+=item B<wrap_method_body>
+
 =item B<alias_method>
 
 =item B<get_method_list>