2 package Moose::Meta::Class;
10 use List::Util qw( first );
11 use List::MoreUtils qw( any all );
12 use Scalar::Util 'weaken', 'blessed';
14 our $VERSION = '0.57';
15 $VERSION = eval $VERSION;
16 our $AUTHORITY = 'cpan:STEVAN';
18 use Moose::Meta::Method::Overriden;
19 use Moose::Meta::Method::Augmented;
21 use base 'Class::MOP::Class';
23 __PACKAGE__->meta->add_attribute('roles' => (
28 __PACKAGE__->meta->add_attribute('constructor_class' => (
29 accessor => 'constructor_class',
30 default => sub { 'Moose::Meta::Method::Constructor' }
33 __PACKAGE__->meta->add_attribute('destructor_class' => (
34 accessor => 'destructor_class',
35 default => sub { 'Moose::Meta::Method::Destructor' }
38 __PACKAGE__->meta->add_attribute('error_builder' => (
39 reader => 'error_builder',
43 __PACKAGE__->meta->add_attribute('error_class' => (
44 reader => 'error_class',
51 return Class::MOP::get_metaclass_by_name($pkg)
52 || $class->SUPER::initialize($pkg,
53 'attribute_metaclass' => 'Moose::Meta::Attribute',
54 'method_metaclass' => 'Moose::Meta::Method',
55 'instance_metaclass' => 'Moose::Meta::Instance',
61 my ($self, $package_name, %options) = @_;
63 (ref $options{roles} eq 'ARRAY')
64 || $self->throw_error("You must pass an ARRAY ref of roles", data => $options{roles})
65 if exists $options{roles};
67 my $class = $self->SUPER::create($package_name, %options);
69 if (exists $options{roles}) {
70 Moose::Util::apply_all_roles($class, @{$options{roles}});
76 sub check_metaclass_compatibility {
79 if ( my @supers = $self->superclasses ) {
80 $self->_fix_metaclass_incompatibility(@supers);
83 $self->SUPER::check_metaclass_compatibility(@_);
88 sub create_anon_class {
89 my ($self, %options) = @_;
91 my $cache_ok = delete $options{cache};
93 # something like Super::Class|Super::Class::2=Role|Role::1
94 my $cache_key = join '=' => (
95 join('|', sort @{$options{superclasses} || []}),
96 join('|', sort @{$options{roles} || []}),
99 if ($cache_ok && defined $ANON_CLASSES{$cache_key}) {
100 return $ANON_CLASSES{$cache_key};
103 my $new_class = $self->SUPER::create_anon_class(%options);
105 $ANON_CLASSES{$cache_key} = $new_class
112 my ($self, $role) = @_;
113 (blessed($role) && $role->isa('Moose::Meta::Role'))
114 || $self->throw_error("Roles must be instances of Moose::Meta::Role", data => $role);
115 push @{$self->roles} => $role;
118 sub calculate_all_roles {
121 grep { !$seen{$_->name}++ } map { $_->calculate_all_roles } @{ $self->roles };
125 my ($self, $role_name) = @_;
127 || $self->throw_error("You must supply a role name to look for");
128 foreach my $class ($self->class_precedence_list) {
129 next unless $class->can('meta') && $class->meta->can('roles');
130 foreach my $role (@{$class->meta->roles}) {
131 return 1 if $role->does_role($role_name);
138 my ($self, $role_name) = @_;
140 || $self->throw_error("You must supply a role name to look for");
141 foreach my $class ($self->class_precedence_list) {
142 next unless $class->can('meta');
144 # in the pretty rare instance when a Moose metaclass
145 # is itself extended with a role, this check needs to
146 # be done since some items in the class_precedence_list
147 # might in fact be Class::MOP based still.
148 next unless $class->meta->can('roles');
149 foreach my $role (@{$class->meta->roles}) {
150 return 1 if $role->excludes_role($role_name);
158 my $params = @_ == 1 ? $_[0] : {@_};
159 my $self = $class->SUPER::new_object($params);
160 foreach my $attr ($class->compute_all_applicable_attributes()) {
161 # if we have a trigger, then ...
162 if ($attr->can('has_trigger') && $attr->has_trigger) {
163 # make sure we have an init-arg ...
164 if (defined(my $init_arg = $attr->init_arg)) {
165 # now make sure an init-arg was passes ...
166 if (exists $params->{$init_arg}) {
167 # and if get here, fire the trigger
170 # check if there is a coercion
171 ($attr->should_coerce
172 # and if so, we need to grab the
173 # value that is actually been stored
174 ? $attr->get_read_method_ref->($self)
175 # otherwise, just get the value from
176 # the constructor params
177 : $params->{$init_arg}),
187 sub construct_instance {
189 my $params = @_ == 1 ? $_[0] : {@_};
190 my $meta_instance = $class->get_meta_instance;
192 # the code below is almost certainly incorrect
193 # but this is foreign inheritence, so we might
194 # have to kludge it in the end.
195 my $instance = $params->{'__INSTANCE__'} || $meta_instance->create_instance();
196 foreach my $attr ($class->compute_all_applicable_attributes()) {
197 $attr->initialize_instance_slot($meta_instance, $instance, $params);
207 my $current = Class::MOP::check_package_cache_flag($self->name);
209 if (defined $self->{'_package_cache_flag'} && $self->{'_package_cache_flag'} == $current) {
210 return $self->{'methods'};
213 $self->{_package_cache_flag} = $current;
215 my $map = $self->{'methods'};
217 my $class_name = $self->name;
218 my $method_metaclass = $self->method_metaclass;
220 my %all_code = $self->get_all_package_symbols('CODE');
222 foreach my $symbol (keys %all_code) {
223 my $code = $all_code{$symbol};
225 next if exists $map->{$symbol} &&
226 defined $map->{$symbol} &&
227 $map->{$symbol}->body == $code;
229 my ($pkg, $name) = Class::MOP::get_code_info($code);
231 if ($pkg->can('meta')
233 # we don't know what ->meta we are calling
234 # here, so we need to be careful cause it
235 # just might blow up at us, or just complain
236 # loudly (in the case of Curses.pm) so we
237 # just be a little overly cautious here.
239 && eval { no warnings; blessed($pkg->meta) }
240 && $pkg->meta->isa('Moose::Meta::Role')) {
241 #my $role = $pkg->meta->name;
242 #next unless $self->does_role($role);
247 # in 5.10 constant.pm the constants show up
248 # as being in the right package, but in pre-5.10
249 # they show up as constant::__ANON__ so we
250 # make an exception here to be sure that things
251 # work as expected in both.
253 unless ($pkg eq 'constant' && $name eq '__ANON__') {
254 next if ($pkg || '') ne $class_name ||
255 (($name || '') ne '__ANON__' && ($pkg || '') ne $class_name);
260 $map->{$symbol} = $method_metaclass->wrap(
262 package_name => $class_name,
270 ### ---------------------------------------------
274 $self->SUPER::add_attribute(
275 (blessed $_[0] && $_[0]->isa('Class::MOP::Attribute')
277 : $self->_process_attribute(@_))
281 sub add_override_method_modifier {
282 my ($self, $name, $method, $_super_package) = @_;
284 (!$self->has_method($name))
285 || $self->throw_error("Cannot add an override method if a local method is already present");
287 $self->add_method($name => Moose::Meta::Method::Overriden->new(
290 package => $_super_package, # need this for roles
295 sub add_augment_method_modifier {
296 my ($self, $name, $method) = @_;
297 (!$self->has_method($name))
298 || $self->throw_error("Cannot add an augment method if a local method is already present");
300 $self->add_method($name => Moose::Meta::Method::Augmented->new(
307 ## Private Utility methods ...
309 sub _find_next_method_by_name_which_is_not_overridden {
310 my ($self, $name) = @_;
311 foreach my $method ($self->find_all_methods_by_name($name)) {
312 return $method->{code}
313 if blessed($method->{code}) && !$method->{code}->isa('Moose::Meta::Method::Overriden');
318 sub _fix_metaclass_incompatibility {
319 my ($self, @superclasses) = @_;
321 foreach my $super (@superclasses) {
322 next if $self->_superclass_meta_is_compatible($super);
324 unless ( $self->is_pristine ) {
326 "Cannot attempt to reinitialize metaclass for "
328 . ", it isn't pristine" );
331 $self->_reconcile_with_superclass_meta($super);
335 sub _superclass_meta_is_compatible {
336 my ($self, $super) = @_;
338 my $super_meta = Class::MOP::Class->initialize($super)
341 next unless $super_meta->isa("Class::MOP::Class");
344 = $super_meta->is_immutable
345 ? $super_meta->get_mutable_metaclass_name
349 if $self->isa($super_meta_name)
351 $self->instance_metaclass->isa( $super_meta->instance_metaclass );
354 # I don't want to have to type this >1 time
356 qw( attribute_metaclass method_metaclass instance_metaclass constructor_class destructor_class );
358 sub _reconcile_with_superclass_meta {
359 my ($self, $super) = @_;
361 my $super_meta = $super->meta;
364 = $super_meta->is_immutable
365 ? $super_meta->get_mutable_metaclass_name
368 my $self_metaclass = ref $self;
370 # If neither of these is true we have a more serious
371 # incompatibility that we just cannot fix (yet?).
372 if ( $super_meta_name->isa( ref $self )
373 && all { $super_meta->$_->isa( $self->$_ ) } @MetaClassTypes ) {
374 $self->_reinitialize_with($super_meta);
376 elsif ( $self->_all_metaclasses_differ_by_roles_only($super_meta) ) {
377 $self->_reconcile_role_differences($super_meta);
381 sub _reinitialize_with {
382 my ( $self, $new_meta ) = @_;
384 my $new_self = $new_meta->reinitialize(
386 attribute_metaclass => $new_meta->attribute_metaclass,
387 method_metaclass => $new_meta->method_metaclass,
388 instance_metaclass => $new_meta->instance_metaclass,
391 $new_self->$_( $new_meta->$_ ) for qw( constructor_class destructor_class );
395 bless $self, ref $new_self;
397 # FIXME? This seems to be necessary in some cases because of how
398 # Class::MOP::Class->construct_class_instance will weaken the
399 # metaclass store entry for an anonymous class. However, if that
400 # anonymous class is a metaclass's metaclass, we don't want it
401 # going out of scope. I'm not sure this is the right fix at all.
402 Class::MOP::store_metaclass_by_name( $self->name, $self );
405 # In the more complex case, we share a common ancestor with our
406 # superclass's metaclass, but each metaclass (ours and the parent's)
407 # has a different set of roles applied. We reconcile this by first
408 # reinitializing into the parent class, and _then_ applying our own
410 sub _all_metaclasses_differ_by_roles_only {
411 my ($self, $super_meta) = @_;
414 [ ref $self, ref $super_meta ],
415 map { [ $self->$_, $super_meta->$_ ] } @MetaClassTypes
418 next if $pair->[0] eq $pair->[1];
420 my $self_meta_meta = Class::MOP::Class->initialize( $pair->[0] );
421 my $super_meta_meta = Class::MOP::Class->initialize( $pair->[1] );
424 = _find_common_ancestor( $self_meta_meta, $super_meta_meta );
426 return unless $common_ancestor;
429 unless _is_role_only_subclass_of(
433 && _is_role_only_subclass_of(
442 # This, and some other functions, could be called as methods, but
443 # they're not for two reasons. One, we just end up ignoring the first
444 # argument, because we can't call these directly on one of the real
445 # arguments, because one of them could be a Class::MOP::Class object
446 # and not a Moose::Meta::Class. Second, only a completely insane
447 # person would attempt to subclass this stuff!
448 sub _find_common_ancestor {
449 my ($meta1, $meta2) = @_;
451 # FIXME? This doesn't account for multiple inheritance (not sure
452 # if it needs to though). For example, is somewhere in $meta1's
453 # history it inherits from both ClassA and ClassB, and $meta
454 # inherits from ClassB & ClassA, does it matter? And what crazy
455 # fool would do that anyway?
457 my %meta1_parents = map { $_ => 1 } $meta1->linearized_isa;
459 return first { $meta1_parents{$_} } $meta2->linearized_isa;
462 sub _is_role_only_subclass_of {
463 my ($meta, $ancestor) = @_;
465 return 1 if $meta->name eq $ancestor;
467 my @roles = _all_roles_until( $meta, $ancestor );
469 my %role_packages = map { $_->name => 1 } @roles;
471 my $ancestor_meta = Class::MOP::Class->initialize($ancestor);
473 my %shared_ancestors = map { $_ => 1 } $ancestor_meta->linearized_isa;
475 for my $method ( $meta->get_all_methods() ) {
476 next if $method->name eq 'meta';
477 next if $method->can('associated_attribute');
480 if $role_packages{ $method->original_package_name }
481 || $shared_ancestors{ $method->original_package_name };
486 # FIXME - this really isn't right. Just because an attribute is
487 # defined in a role doesn't mean it isn't _also_ defined in the
489 for my $attr ( $meta->get_all_attributes ) {
490 next if $shared_ancestors{ $attr->associated_class->name };
492 next if any { $_->has_attribute( $attr->name ) } @roles;
503 return _all_roles_until($meta);
506 sub _all_roles_until {
507 my ($meta, $stop_at_class) = @_;
509 return unless $meta->can('calculate_all_roles');
511 my @roles = $meta->calculate_all_roles;
513 for my $class ( $meta->linearized_isa ) {
514 last if $stop_at_class && $stop_at_class eq $class;
516 my $meta = Class::MOP::Class->initialize($class);
517 last unless $meta->can('calculate_all_roles');
519 push @roles, $meta->calculate_all_roles;
525 sub _reconcile_role_differences {
526 my ($self, $super_meta) = @_;
528 my $self_meta = $self->meta;
532 if ( my @roles = map { $_->name } _all_roles($self_meta) ) {
533 $roles{metaclass_roles} = \@roles;
536 for my $thing (@MetaClassTypes) {
537 my $name = $self->$thing();
539 my $thing_meta = Class::MOP::Class->initialize($name);
541 my @roles = map { $_->name } _all_roles($thing_meta)
544 $roles{ $thing . '_roles' } = \@roles;
547 $self->_reinitialize_with($super_meta);
549 Moose::Util::MetaRole::apply_metaclass_roles(
550 for_class => $self->name,
558 # this was crap anyway, see
559 # Moose::Util::apply_all_roles
561 sub _apply_all_roles {
562 Carp::croak 'DEPRECATED: use Moose::Util::apply_all_roles($meta, @roles) instead'
565 sub _process_attribute {
566 my ( $self, $name, @args ) = @_;
568 @args = %{$args[0]} if scalar @args == 1 && ref($args[0]) eq 'HASH';
570 if ($name =~ /^\+(.*)/) {
571 return $self->_process_inherited_attribute($1, @args);
574 return $self->_process_new_attribute($name, @args);
578 sub _process_new_attribute {
579 my ( $self, $name, @args ) = @_;
581 $self->attribute_metaclass->interpolate_class_and_new($name, @args);
584 sub _process_inherited_attribute {
585 my ($self, $attr_name, %options) = @_;
586 my $inherited_attr = $self->find_attribute_by_name($attr_name);
587 (defined $inherited_attr)
588 || $self->throw_error("Could not find an attribute by the name of '$attr_name' to inherit from", data => $attr_name);
589 if ($inherited_attr->isa('Moose::Meta::Attribute')) {
590 return $inherited_attr->clone_and_inherit_options(%options);
594 # kind of a kludge to handle Class::MOP::Attributes
595 return $inherited_attr->Moose::Meta::Attribute::clone_and_inherit_options(%options);
599 ## -------------------------------------------------
601 use Moose::Meta::Method::Constructor;
602 use Moose::Meta::Method::Destructor;
604 # This could be done by using SUPER and altering ->options
605 # I am keeping it this way to make it more explicit.
606 sub create_immutable_transformer {
608 my $class = Class::MOP::Immutable->new($self, {
609 read_only => [qw/superclasses/],
616 remove_package_symbol
620 class_precedence_list => 'ARRAY',
621 linearized_isa => 'ARRAY', # FIXME perl 5.10 memoizes this on its own, no need?
622 get_all_methods => 'ARRAY',
623 #get_all_attributes => 'ARRAY', # it's an alias, no need, but maybe in the future
624 compute_all_applicable_attributes => 'ARRAY',
625 get_meta_instance => 'SCALAR',
626 get_method_map => 'SCALAR',
627 calculate_all_roles => 'ARRAY',
630 # this is ugly, but so are typeglobs,
631 # so whattayahgonnadoboutit
634 add_package_symbol => sub {
635 my $original = shift;
636 $self->throw_error("Cannot add package symbols to an immutable metaclass")
637 unless (caller(2))[3] eq 'Class::MOP::Package::get_package_symbol';
638 goto $original->body;
647 $self->SUPER::make_immutable
649 constructor_class => $self->constructor_class,
650 destructor_class => $self->destructor_class,
651 inline_destructor => 1,
653 # no need to do this,
654 # Moose always does it
655 inline_accessors => 0,
660 #{ package Moose::Meta::Class::ErrorRoutines; %Carp::Internal?
665 my ( $self, @args ) = @_;
667 $self->raise_error($self->create_error(@args));
671 my ( $self, @args ) = @_;
676 my ( $self, @args ) = @_;
678 if ( @args % 2 == 1 ) {
679 unshift @args, "message";
682 my %args = ( meta => $self, error => $@, @args );
684 local $level = $level + 1;
686 if ( my $class = $args{class} || ( ref $self && $self->error_class ) ) {
687 return $self->create_error_object( %args, class => $class );
689 my $builder = $args{builder} || ( ref($self) ? $self->error_builder : "confess" );
691 my $builder_method = ( ( ref($builder) && ref($builder) eq 'CODE' )
693 : ( $self->can("create_error_$builder") || "create_error_confess" ));
695 return $self->$builder_method(%args);
699 sub create_error_object {
700 my ( $self, %args ) = @_;
702 my $class = delete $args{class};
706 depth => ( ($args{depth} || 1) + ( $level + 1 ) ),
710 sub create_error_croak {
711 my ( $self, @args ) = @_;
712 $self->_create_error_carpmess( @args );
715 sub create_error_confess {
716 my ( $self, @args ) = @_;
717 $self->_create_error_carpmess( @args, longmess => 1 );
720 sub _create_error_carpmess {
721 my ( $self, %args ) = @_;
723 my $carp_level = $level + 1 + ( $args{depth} || 1 );
725 local $Carp::CarpLevel = $carp_level; # $Carp::CarpLevel + $carp_level ?
726 local $Carp::MaxArgNums = 20; # default is 8, usually we use named args which gets messier though
728 my @args = exists $args{message} ? $args{message} : ();
730 if ( $args{longmess} ) {
731 return Carp::longmess(@args);
733 return Carp::shortmess(@args);
745 Moose::Meta::Class - The Moose metaclass
749 This is a subclass of L<Class::MOP::Class> with Moose specific
752 For the most part, the only time you will ever encounter an
753 instance of this class is if you are doing some serious deep
754 introspection. To really understand this class, you need to refer
755 to the L<Class::MOP::Class> documentation.
765 Overrides original to accept a list of roles to apply to
768 my $metaclass = Moose::Meta::Class->create( 'New::Class', roles => [...] );
770 =item B<create_anon_class>
772 Overrides original to support roles and caching.
774 my $metaclass = Moose::Meta::Class->create_anon_class(
775 superclasses => ['Foo'],
776 roles => [qw/Some Roles Go Here/],
780 =item B<make_immutable>
782 Override original to add default options for inlining destructor
783 and altering the Constructor metaclass.
785 =item B<create_immutable_transformer>
787 Override original to lock C<add_role> and memoize C<calculate_all_roles>
791 We override this method to support the C<trigger> attribute option.
793 =item B<construct_instance>
795 This provides some Moose specific extensions to this method, you
796 almost never call this method directly unless you really know what
799 This method makes sure to handle the moose weak-ref, type-constraint
800 and type coercion features.
802 =item B<get_method_map>
804 This accommodates Moose::Meta::Role::Method instances, which are
805 aliased, instead of added, but still need to be counted as valid
808 =item B<add_override_method_modifier ($name, $method)>
810 This will create an C<override> method modifier for you, and install
813 =item B<add_augment_method_modifier ($name, $method)>
815 This will create an C<augment> method modifier for you, and install
818 =item B<calculate_all_roles>
822 This will return an array of C<Moose::Meta::Role> instances which are
823 attached to this class.
825 =item B<add_role ($role)>
827 This takes an instance of C<Moose::Meta::Role> in C<$role>, and adds it
828 to the list of associated roles.
830 =item B<does_role ($role_name)>
832 This will test if this class C<does> a given C<$role_name>. It will
833 not only check it's local roles, but ask them as well in order to
834 cascade down the role hierarchy.
836 =item B<excludes_role ($role_name)>
838 This will test if this class C<excludes> a given C<$role_name>. It will
839 not only check it's local roles, but ask them as well in order to
840 cascade down the role hierarchy.
842 =item B<add_attribute ($attr_name, %params|$params)>
844 This method does the same thing as L<Class::MOP::Class::add_attribute>, but adds
845 support for taking the C<$params> as a HASH ref.
847 =item B<constructor_class ($class_name)>
849 =item B<destructor_class ($class_name)>
851 These are the names of classes used when making a class
852 immutable. These default to L<Moose::Meta::Method::Constructor> and
853 L<Moose::Meta::Method::Destructor> respectively. These accessors are
854 read-write, so you can use them to change the class name.
856 =item B<throw_error $message, %extra>
858 Throws the error created by C<create_error> using C<raise_error>
860 =item B<create_error $message, %extra>
862 Creates an error message or object.
864 The default behavior is C<create_error_confess>.
866 If C<error_class> is set uses C<create_error_object>. Otherwise uses
867 C<error_builder> (a code reference or variant name), and calls the appropriate
868 C<create_error_$builder> method.
870 =item B<error_builder $builder_name>
872 Get or set the error builder. Defaults to C<confess>.
874 =item B<error_class $class_name>
876 Get or set the error class. Has no default.
878 =item B<create_error_confess %args>
880 Creates an error using L<Carp/longmess>
882 =item B<create_error_croak %args>
884 Creates an error using L<Carp/shortmess>
886 =item B<create_error_object %args>
888 Calls C<new> on the C<class> parameter in C<%args>. Usable with C<error_class>
889 to support custom error objects for your meta class.
891 =item B<raise_error $error>
893 Dies with an error object or string.
899 All complex software has bugs lurking in it, and this module is no
900 exception. If you find a bug please either email me, or add the bug
905 Stevan Little E<lt>stevan@iinteractive.comE<gt>
907 =head1 COPYRIGHT AND LICENSE
909 Copyright 2006-2008 by Infinity Interactive, Inc.
911 L<http://www.iinteractive.com>
913 This library is free software; you can redistribute it and/or modify
914 it under the same terms as Perl itself.