bump version to 1.12
[gitmo/Moose.git] / lib / Moose / Meta / Class.pm
index a0ba807..7e1788a 100644 (file)
@@ -12,7 +12,7 @@ use List::Util qw( first );
 use List::MoreUtils qw( any all uniq first_index );
 use Scalar::Util 'weaken', 'blessed';
 
-our $VERSION   = '1.04';
+our $VERSION   = '1.12';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
@@ -401,16 +401,32 @@ sub _is_role_only_subclass {
     my ($parent_name) = @parent_names;
     my $parent_meta = Class::MOP::Class->initialize($parent_name);
 
+    my @roles = $meta->can('calculate_all_roles_with_inheritance')
+                    ? $meta->calculate_all_roles_with_inheritance
+                    : ();
+
     # loop over all methods that are a part of the current class
     # (not inherited)
-    for my $method (map { $meta->get_method($_) } $meta->get_method_list) {
+    for my $method ( $meta->_get_local_methods ) {
         # always ignore meta
         next if $method->name eq 'meta';
         # we'll deal with attributes below
-        next if $method->isa('Class::MOP::Method::Accessor');
+        next if $method->can('associated_attribute');
         # if the method comes from a role we consumed, ignore it
         next if $meta->can('does_role')
              && $meta->does_role($method->original_package_name);
+        # FIXME - this really isn't right. Just because a modifier is
+        # defined in a role doesn't mean it isn't _also_ defined in the
+        # subclass.
+        next if $method->isa('Class::MOP::Method::Wrapped')
+             && (
+                 (!scalar($method->around_modifiers)
+               || any { $_->has_around_method_modifiers($method->name) } @roles)
+              && (!scalar($method->before_modifiers)
+               || any { $_->has_before_method_modifiers($method->name) } @roles)
+              && (!scalar($method->after_modifiers)
+               || any { $_->has_after_method_modifiers($method->name) } @roles)
+                );
 
         return 0;
     }
@@ -421,8 +437,7 @@ sub _is_role_only_subclass {
     # defined in a role doesn't mean it isn't _also_ defined in the
     # subclass.
     for my $attr (map { $meta->get_attribute($_) } $meta->get_attribute_list) {
-        next if any { $_->has_attribute($attr->name) }
-                    $meta->calculate_all_roles_with_inheritance;
+        next if any { $_->has_attribute($attr->name) } @roles;
 
         return 0;
     }
@@ -510,6 +525,14 @@ sub _reconcile_roles_for_metaclass {
     my @role_differences = $self->_role_differences(
         $class_meta_name, $super_meta_name,
     );
+
+    # handle the case where we need to fix compatibility between a class and
+    # its parent, but all roles in the class are already also done by the
+    # parent
+    # see t/050/054.t
+    return Class::MOP::class_of($super_meta_name)
+        unless @role_differences;
+
     return Moose::Meta::Class->create_anon_class(
         superclasses => [$super_meta_name],
         roles        => \@role_differences,
@@ -570,13 +593,14 @@ sub _fix_single_metaclass_incompatibility {
             || confess "Can't fix metaclass incompatibility for "
                      . $self->name
                      . " because it is not pristine.";
+        my $super_meta_name = $super_meta->_real_ref_name;
         my $class_specific_meta_subclass_meta = $self->_reconcile_roles_for_metaclass($self->$metaclass_type, $super_meta->$metaclass_type);
         my $new_self = $super_meta->reinitialize(
             $self->name,
             $metaclass_type => $class_specific_meta_subclass_meta->name,
         );
 
-        $self->_replace_self( $new_self, blessed($super_meta) );
+        $self->_replace_self( $new_self, $super_meta_name );
     }
 }