2 package Moose::Meta::Class;
11 use List::Util qw( first );
12 use List::MoreUtils qw( any all uniq first_index );
13 use Scalar::Util 'weaken', 'blessed';
15 our $VERSION = '1.02';
16 $VERSION = eval $VERSION;
17 our $AUTHORITY = 'cpan:STEVAN';
19 use Moose::Meta::Method::Overridden;
20 use Moose::Meta::Method::Augmented;
21 use Moose::Error::Default;
22 use Moose::Meta::Class::Immutable::Trait;
23 use Moose::Meta::Method::Constructor;
24 use Moose::Meta::Method::Destructor;
26 use base 'Class::MOP::Class';
28 __PACKAGE__->meta->add_attribute('roles' => (
33 __PACKAGE__->meta->add_attribute('role_applications' => (
34 reader => '_get_role_applications',
38 __PACKAGE__->meta->add_attribute(
39 Class::MOP::Attribute->new('immutable_trait' => (
40 accessor => "immutable_trait",
41 default => 'Moose::Meta::Class::Immutable::Trait',
45 __PACKAGE__->meta->add_attribute('constructor_class' => (
46 accessor => 'constructor_class',
47 default => 'Moose::Meta::Method::Constructor',
50 __PACKAGE__->meta->add_attribute('destructor_class' => (
51 accessor => 'destructor_class',
52 default => 'Moose::Meta::Method::Destructor',
55 __PACKAGE__->meta->add_attribute('error_class' => (
56 accessor => 'error_class',
57 default => 'Moose::Error::Default',
63 return Class::MOP::get_metaclass_by_name($pkg)
64 || $class->SUPER::initialize($pkg,
65 'attribute_metaclass' => 'Moose::Meta::Attribute',
66 'method_metaclass' => 'Moose::Meta::Method',
67 'instance_metaclass' => 'Moose::Meta::Instance',
72 sub _immutable_options {
73 my ( $self, @args ) = @_;
75 $self->SUPER::_immutable_options(
76 inline_destructor => 1,
78 # Moose always does this when an attribute is created
79 inline_accessors => 0,
86 my ($self, $package_name, %options) = @_;
88 (ref $options{roles} eq 'ARRAY')
89 || $self->throw_error("You must pass an ARRAY ref of roles", data => $options{roles})
90 if exists $options{roles};
91 my $roles = delete $options{roles};
93 my $class = $self->SUPER::create($package_name, %options);
96 Moose::Util::apply_all_roles( $class, @$roles );
102 sub _check_metaclass_compatibility {
105 if ( my @supers = $self->superclasses ) {
106 $self->_fix_metaclass_incompatibility(@supers);
109 $self->SUPER::_check_metaclass_compatibility(@_);
114 sub create_anon_class {
115 my ($self, %options) = @_;
117 my $cache_ok = delete $options{cache};
120 = _anon_cache_key( $options{superclasses}, $options{roles} );
122 if ($cache_ok && defined $ANON_CLASSES{$cache_key}) {
123 return $ANON_CLASSES{$cache_key};
126 my $new_class = $self->SUPER::create_anon_class(%options);
128 $ANON_CLASSES{$cache_key} = $new_class
134 sub _anon_cache_key {
135 # Makes something like Super::Class|Super::Class::2=Role|Role::1
137 join( '|', @{ $_[0] || [] } ),
138 join( '|', sort @{ $_[1] || [] } ),
146 my $meta = blessed $pkg ? $pkg : Class::MOP::class_of($pkg);
150 my %existing_classes;
152 %existing_classes = map { $_ => $meta->$_() } qw(
155 wrapped_method_metaclass
162 $cache_key = _anon_cache_key(
163 [ $meta->superclasses ],
164 [ map { $_->name } @{ $meta->roles } ],
165 ) if $meta->is_anon_class;
168 my $new_meta = $self->SUPER::reinitialize(
174 return $new_meta unless defined $cache_key;
176 my $new_cache_key = _anon_cache_key(
177 [ $meta->superclasses ],
178 [ map { $_->name } @{ $meta->roles } ],
181 delete $ANON_CLASSES{$cache_key};
182 $ANON_CLASSES{$new_cache_key} = $new_meta;
188 my ($self, $role) = @_;
189 (blessed($role) && $role->isa('Moose::Meta::Role'))
190 || $self->throw_error("Roles must be instances of Moose::Meta::Role", data => $role);
191 push @{$self->roles} => $role;
194 sub role_applications {
197 return @{$self->_get_role_applications};
200 sub add_role_application {
201 my ($self, $application) = @_;
202 (blessed($application) && $application->isa('Moose::Meta::Role::Application::ToClass'))
203 || $self->throw_error("Role applications must be instances of Moose::Meta::Role::Application::ToClass", data => $application);
204 push @{$self->_get_role_applications} => $application;
207 sub calculate_all_roles {
210 grep { !$seen{$_->name}++ } map { $_->calculate_all_roles } @{ $self->roles };
214 my ($self, $role_name) = @_;
217 || $self->throw_error("You must supply a role name to look for");
219 foreach my $class ($self->class_precedence_list) {
220 my $meta = Class::MOP::class_of($class);
221 # when a Moose metaclass is itself extended with a role,
222 # this check needs to be done since some items in the
223 # class_precedence_list might in fact be Class::MOP
225 next unless $meta && $meta->can('roles');
226 foreach my $role (@{$meta->roles}) {
227 return 1 if $role->does_role($role_name);
234 my ($self, $role_name) = @_;
237 || $self->throw_error("You must supply a role name to look for");
239 foreach my $class ($self->class_precedence_list) {
240 my $meta = Class::MOP::class_of($class);
241 # when a Moose metaclass is itself extended with a role,
242 # this check needs to be done since some items in the
243 # class_precedence_list might in fact be Class::MOP
245 next unless $meta && $meta->can('roles');
246 foreach my $role (@{$meta->roles}) {
247 return 1 if $role->excludes_role($role_name);
255 my $params = @_ == 1 ? $_[0] : {@_};
256 my $self = $class->SUPER::new_object($params);
258 foreach my $attr ( $class->get_all_attributes() ) {
260 next unless $attr->can('has_trigger') && $attr->has_trigger;
262 my $init_arg = $attr->init_arg;
264 next unless defined $init_arg;
266 next unless exists $params->{$init_arg};
272 ? $attr->get_read_method_ref->($self)
273 : $params->{$init_arg}
283 my $supers = Data::OptList::mkopt(\@_);
284 foreach my $super (@{ $supers }) {
285 my ($name, $opts) = @{ $super };
286 Class::MOP::load_class($name, $opts);
287 my $meta = Class::MOP::class_of($name);
288 $self->throw_error("You cannot inherit from a Moose Role ($name)")
289 if $meta && $meta->isa('Moose::Meta::Role')
291 return $self->SUPER::superclasses(map { $_->[0] } @{ $supers });
294 ### ---------------------------------------------
299 (blessed $_[0] && $_[0]->isa('Class::MOP::Attribute')
301 : $self->_process_attribute(@_));
302 $self->SUPER::add_attribute($attr);
303 # it may be a Class::MOP::Attribute, theoretically, which doesn't have
304 # 'bare' and doesn't implement this method
305 if ($attr->can('_check_associated_methods')) {
306 $attr->_check_associated_methods;
311 sub add_override_method_modifier {
312 my ($self, $name, $method, $_super_package) = @_;
314 (!$self->has_method($name))
315 || $self->throw_error("Cannot add an override method if a local method is already present");
317 $self->add_method($name => Moose::Meta::Method::Overridden->new(
320 package => $_super_package, # need this for roles
325 sub add_augment_method_modifier {
326 my ($self, $name, $method) = @_;
327 (!$self->has_method($name))
328 || $self->throw_error("Cannot add an augment method if a local method is already present");
330 $self->add_method($name => Moose::Meta::Method::Augmented->new(
337 ## Private Utility methods ...
339 sub _find_next_method_by_name_which_is_not_overridden {
340 my ($self, $name) = @_;
341 foreach my $method ($self->find_all_methods_by_name($name)) {
342 return $method->{code}
343 if blessed($method->{code}) && !$method->{code}->isa('Moose::Meta::Method::Overridden');
348 sub _fix_metaclass_incompatibility {
349 my ($self, @superclasses) = @_;
351 $self->_fix_one_incompatible_metaclass($_)
352 for map { Moose::Meta::Class->initialize($_) } @superclasses;
355 sub _fix_one_incompatible_metaclass {
356 my ($self, $meta) = @_;
358 return if $self->_superclass_meta_is_compatible($meta);
360 unless ( $self->is_pristine ) {
362 "Cannot attempt to reinitialize metaclass for "
364 . ", it isn't pristine" );
367 $self->_reconcile_with_superclass_meta($meta);
370 sub _superclass_meta_is_compatible {
371 my ($self, $super_meta) = @_;
373 next unless $super_meta->isa("Class::MOP::Class");
376 = $super_meta->is_immutable
377 ? $super_meta->_get_mutable_metaclass_name
381 if $self->isa($super_meta_name)
383 $self->instance_metaclass->isa( $super_meta->instance_metaclass );
386 # I don't want to have to type this >1 time
388 qw( attribute_metaclass
390 wrapped_method_metaclass
396 sub _reconcile_with_superclass_meta {
397 my ($self, $super_meta) = @_;
400 = $super_meta->is_immutable
401 ? $super_meta->_get_mutable_metaclass_name
404 my $self_metaclass = ref $self;
406 # If neither of these is true we have a more serious
407 # incompatibility that we just cannot fix (yet?).
408 if ( $super_meta_name->isa( ref $self )
409 && all { $super_meta->$_->isa( $self->$_ ) } @MetaClassTypes ) {
410 $self->_reinitialize_with($super_meta);
412 elsif ( $self->_all_metaclasses_differ_by_roles_only($super_meta) ) {
413 $self->_reconcile_role_differences($super_meta);
417 sub _reinitialize_with {
418 my ( $self, $new_meta ) = @_;
420 my $new_self = $new_meta->reinitialize(
422 attribute_metaclass => $new_meta->attribute_metaclass,
423 method_metaclass => $new_meta->method_metaclass,
424 instance_metaclass => $new_meta->instance_metaclass,
427 $new_self->$_( $new_meta->$_ )
428 for qw( constructor_class destructor_class error_class );
432 bless $self, ref $new_self;
434 # We need to replace the cached metaclass instance or else when it
435 # goes out of scope Class::MOP::Class destroy's the namespace for
436 # the metaclass's class, causing much havoc.
437 Class::MOP::store_metaclass_by_name( $self->name, $self );
438 Class::MOP::weaken_metaclass( $self->name ) if $self->is_anon_class;
441 # In the more complex case, we share a common ancestor with our
442 # superclass's metaclass, but each metaclass (ours and the parent's)
443 # has a different set of roles applied. We reconcile this by first
444 # reinitializing into the parent class, and _then_ applying our own
446 sub _all_metaclasses_differ_by_roles_only {
447 my ($self, $super_meta) = @_;
450 [ ref $self, ref $super_meta ],
451 map { [ $self->$_, $super_meta->$_ ] } @MetaClassTypes
454 next if $pair->[0] eq $pair->[1];
456 my $self_meta_meta = Class::MOP::Class->initialize( $pair->[0] );
457 my $super_meta_meta = Class::MOP::Class->initialize( $pair->[1] );
460 = _find_common_ancestor( $self_meta_meta, $super_meta_meta );
462 return unless $common_ancestor;
465 unless _is_role_only_subclass_of(
469 && _is_role_only_subclass_of(
478 # This, and some other functions, could be called as methods, but
479 # they're not for two reasons. One, we just end up ignoring the first
480 # argument, because we can't call these directly on one of the real
481 # arguments, because one of them could be a Class::MOP::Class object
482 # and not a Moose::Meta::Class. Second, only a completely insane
483 # person would attempt to subclass this stuff!
484 sub _find_common_ancestor {
485 my ($meta1, $meta2) = @_;
487 # FIXME? This doesn't account for multiple inheritance (not sure
488 # if it needs to though). For example, is somewhere in $meta1's
489 # history it inherits from both ClassA and ClassB, and $meta2
490 # inherits from ClassB & ClassA, does it matter? And what crazy
491 # fool would do that anyway?
493 my %meta1_parents = map { $_ => 1 } $meta1->linearized_isa;
495 return first { $meta1_parents{$_} } $meta2->linearized_isa;
498 sub _is_role_only_subclass_of {
499 my ($meta, $ancestor) = @_;
501 return 1 if $meta->name eq $ancestor;
503 my @roles = _all_roles_until( $meta, $ancestor );
505 my %role_packages = map { $_->name => 1 } @roles;
507 my $ancestor_meta = Class::MOP::Class->initialize($ancestor);
509 my %shared_ancestors = map { $_ => 1 } $ancestor_meta->linearized_isa;
511 for my $method ( $meta->get_all_methods() ) {
512 next if $method->name eq 'meta';
513 next if $method->can('associated_attribute');
516 if $role_packages{ $method->original_package_name }
517 || $shared_ancestors{ $method->original_package_name };
522 # FIXME - this really isn't right. Just because an attribute is
523 # defined in a role doesn't mean it isn't _also_ defined in the
525 for my $attr ( $meta->get_all_attributes ) {
526 next if $shared_ancestors{ $attr->associated_class->name };
528 next if any { $_->has_attribute( $attr->name ) } @roles;
539 return _all_roles_until($meta);
542 sub _all_roles_until {
543 my ($meta, $stop_at_class) = @_;
545 return unless $meta->can('calculate_all_roles');
547 my @roles = $meta->calculate_all_roles;
549 for my $class ( $meta->linearized_isa ) {
550 last if $stop_at_class && $stop_at_class eq $class;
552 my $meta = Class::MOP::Class->initialize($class);
553 last unless $meta->can('calculate_all_roles');
555 push @roles, $meta->calculate_all_roles;
561 sub _reconcile_role_differences {
562 my ($self, $super_meta) = @_;
564 my $self_meta = Class::MOP::class_of($self);
568 if ( my @roles = map { $_->name } _all_roles($self_meta) ) {
569 $roles{metaclass_roles} = \@roles;
572 for my $thing (@MetaClassTypes) {
573 my $name = $self->$thing();
575 my $thing_meta = Class::MOP::Class->initialize($name);
577 my @roles = map { $_->name } _all_roles($thing_meta)
580 $roles{ $thing . '_roles' } = \@roles;
583 $self->_reinitialize_with($super_meta);
585 Moose::Util::MetaRole::apply_metaclass_roles(
586 for_class => $self->name,
593 sub _process_attribute {
594 my ( $self, $name, @args ) = @_;
596 @args = %{$args[0]} if scalar @args == 1 && ref($args[0]) eq 'HASH';
598 if (($name || '') =~ /^\+(.*)/) {
599 return $self->_process_inherited_attribute($1, @args);
602 return $self->_process_new_attribute($name, @args);
606 sub _process_new_attribute {
607 my ( $self, $name, @args ) = @_;
609 $self->attribute_metaclass->interpolate_class_and_new($name, @args);
612 sub _process_inherited_attribute {
613 my ($self, $attr_name, %options) = @_;
614 my $inherited_attr = $self->find_attribute_by_name($attr_name);
615 (defined $inherited_attr)
616 || $self->throw_error("Could not find an attribute by the name of '$attr_name' to inherit from in ${\$self->name}", data => $attr_name);
617 if ($inherited_attr->isa('Moose::Meta::Attribute')) {
618 return $inherited_attr->clone_and_inherit_options(%options);
622 # kind of a kludge to handle Class::MOP::Attributes
623 return $inherited_attr->Moose::Meta::Attribute::clone_and_inherit_options(%options);
627 ## -------------------------------------------------
632 my ( $self, @args ) = @_;
633 local $error_level = ($error_level || 0) + 1;
634 $self->raise_error($self->create_error(@args));
638 my ( $self, @args ) = @_;
643 my ( $self, @args ) = @_;
647 local $error_level = ($error_level || 0 ) + 1;
649 if ( @args % 2 == 1 ) {
650 unshift @args, "message";
653 my %args = ( metaclass => $self, last_error => $@, @args );
655 $args{depth} += $error_level;
657 my $class = ref $self ? $self->error_class : "Moose::Error::Default";
659 Class::MOP::load_class($class);
662 Carp::caller_info($args{depth}),
675 Moose::Meta::Class - The Moose metaclass
679 This class is a subclass of L<Class::MOP::Class> that provides
680 additional Moose-specific functionality.
682 To really understand this class, you will need to start with the
683 L<Class::MOP::Class> documentation. This class can be understood as a
684 set of additional features on top of the basic feature provided by
689 C<Moose::Meta::Class> is a subclass of L<Class::MOP::Class>.
695 =item B<< Moose::Meta::Class->initialize($package_name, %options) >>
697 This overrides the parent's method in order to provide its own
698 defaults for the C<attribute_metaclass>, C<instance_metaclass>, and
699 C<method_metaclass> options.
701 These all default to the appropriate Moose class.
703 =item B<< Moose::Meta::Class->create($package_name, %options) >>
705 This overrides the parent's method in order to accept a C<roles>
706 option. This should be an array reference containing roles
707 that the class does, each optionally followed by a hashref of options
708 (C<-excludes> and C<-alias>).
710 my $metaclass = Moose::Meta::Class->create( 'New::Class', roles => [...] );
712 =item B<< Moose::Meta::Class->create_anon_class >>
714 This overrides the parent's method to accept a C<roles> option, just
717 It also accepts a C<cache> option. If this is true, then the anonymous
718 class will be cached based on its superclasses and roles. If an
719 existing anonymous class in the cache has the same superclasses and
720 roles, it will be reused.
722 my $metaclass = Moose::Meta::Class->create_anon_class(
723 superclasses => ['Foo'],
724 roles => [qw/Some Roles Go Here/],
728 Each entry in both the C<superclasses> and the C<roles> option can be
729 followed by a hash reference with arguments. The C<supperclasses>
730 option can be supplied with a L<-version|Class::MOP/Class Loading
731 Options> option that ensures the loaded superclass satisfies the
732 required version. The C<role> option also takes the C<-version> as an
733 argument, but the option hash reference can also contain any other
734 role relevant values like exclusions or parameterized role arguments.
736 =item B<< $metaclass->make_immutable(%options) >>
738 This overrides the parent's method to add a few options. Specifically,
739 it uses the Moose-specific constructor and destructor classes, and
740 enables inlining the destructor.
742 Also, since Moose always inlines attributes, it sets the
743 C<inline_accessors> option to false.
745 =item B<< $metaclass->new_object(%params) >>
747 This overrides the parent's method in order to add support for
750 =item B<< $metaclass->superclasses(@superclasses) >>
752 This is the accessor allowing you to read or change the parents of
755 Each superclass can be followed by a hash reference containing a
756 L<-version|Class::MOP/Class Loading Options> value. If the version
757 requirement is not satisfied an error will be thrown.
759 =item B<< $metaclass->add_override_method_modifier($name, $sub) >>
761 This adds an C<override> method modifier to the package.
763 =item B<< $metaclass->add_augment_method_modifier($name, $sub) >>
765 This adds an C<augment> method modifier to the package.
767 =item B<< $metaclass->calculate_all_roles >>
769 This will return a unique array of C<Moose::Meta::Role> instances
770 which are attached to this class.
772 =item B<< $metaclass->add_role($role) >>
774 This takes a L<Moose::Meta::Role> object, and adds it to the class's
775 list of roles. This I<does not> actually apply the role to the class.
777 =item B<< $metaclass->role_applications >>
779 Returns a list of L<Moose::Meta::Role::Application::ToClass>
780 objects, which contain the arguments to role application.
782 =item B<< $metaclass->add_role_application($application) >>
784 This takes a L<Moose::Meta::Role::Application::ToClass> object, and
785 adds it to the class's list of role applications. This I<does not>
786 actually apply any role to the class; it is only for tracking role
789 =item B<< $metaclass->does_role($role) >>
791 This returns a boolean indicating whether or not the class does the specified
792 role. The role provided can be either a role name or a L<Moose::Meta::Role>
793 object. This tests both the class and its parents.
795 =item B<< $metaclass->excludes_role($role_name) >>
797 A class excludes a role if it has already composed a role which
798 excludes the named role. This tests both the class and its parents.
800 =item B<< $metaclass->add_attribute($attr_name, %params|$params) >>
802 This overrides the parent's method in order to allow the parameters to
803 be provided as a hash reference.
805 =item B<< $metaclass->constructor_class ($class_name) >>
807 =item B<< $metaclass->destructor_class ($class_name) >>
809 These are the names of classes used when making a class
810 immutable. These default to L<Moose::Meta::Method::Constructor> and
811 L<Moose::Meta::Method::Destructor> respectively. These accessors are
812 read-write, so you can use them to change the class name.
814 =item B<< $metaclass->error_class($class_name) >>
816 The name of the class used to throw errors. This defaults to
817 L<Moose::Error::Default>, which generates an error with a stacktrace
818 just like C<Carp::confess>.
820 =item B<< $metaclass->throw_error($message, %extra) >>
822 Throws the error created by C<create_error> using C<raise_error>
828 See L<Moose/BUGS> for details on reporting bugs.
832 Stevan Little E<lt>stevan@iinteractive.comE<gt>
834 =head1 COPYRIGHT AND LICENSE
836 Copyright 2006-2010 by Infinity Interactive, Inc.
838 L<http://www.iinteractive.com>
840 This library is free software; you can redistribute it and/or modify
841 it under the same terms as Perl itself.