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';
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;
}
# 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;
}
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,
|| 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 );
}
}