8908dfa08485d0ae20182310bc63b6fadf0bebf4
[gitmo/Moose.git] / lib / Moose / Meta / Class.pm
1
2 package Moose::Meta::Class;
3
4 use strict;
5 use warnings;
6
7 use Class::MOP;
8
9 use Carp ();
10 use List::Util qw( first );
11 use List::MoreUtils qw( any all uniq first_index );
12 use Scalar::Util 'weaken', 'blessed';
13
14 our $VERSION   = '0.81';
15 $VERSION = eval $VERSION;
16 our $AUTHORITY = 'cpan:STEVAN';
17
18 use Moose::Meta::Method::Overridden;
19 use Moose::Meta::Method::Augmented;
20 use Moose::Error::Default;
21 use Moose::Meta::Class::Immutable::Trait;
22 use Moose::Meta::Method::Constructor;
23 use Moose::Meta::Method::Destructor;
24
25 use base 'Class::MOP::Class';
26
27 __PACKAGE__->meta->add_attribute('roles' => (
28     reader  => 'roles',
29     default => sub { [] }
30 ));
31
32 __PACKAGE__->meta->add_attribute('role_applications' => (
33     reader  => '_get_role_applications',
34     default => sub { [] }
35 ));
36
37 __PACKAGE__->meta->add_attribute(
38     Class::MOP::Attribute->new('immutable_trait' => (
39         accessor => "immutable_trait",
40         default  => 'Moose::Meta::Class::Immutable::Trait',
41     ))
42 );
43
44 __PACKAGE__->meta->add_attribute('constructor_class' => (
45     accessor => 'constructor_class',
46     default  => 'Moose::Meta::Method::Constructor',
47 ));
48
49 __PACKAGE__->meta->add_attribute('destructor_class' => (
50     accessor => 'destructor_class',
51     default  => 'Moose::Meta::Method::Destructor',
52 ));
53
54 __PACKAGE__->meta->add_attribute('error_class' => (
55     accessor => 'error_class',
56     default  => 'Moose::Error::Default',
57 ));
58
59 sub initialize {
60     my $class = shift;
61     my $pkg   = shift;
62     return Class::MOP::get_metaclass_by_name($pkg)
63         || $class->SUPER::initialize($pkg,
64                 'attribute_metaclass' => 'Moose::Meta::Attribute',
65                 'method_metaclass'    => 'Moose::Meta::Method',
66                 'instance_metaclass'  => 'Moose::Meta::Instance',
67                 @_
68             );
69 }
70
71 sub _immutable_options {
72     my ( $self, @args ) = @_;
73
74     $self->SUPER::_immutable_options(
75         inline_destructor => 1,
76
77         # Moose always does this when an attribute is created
78         inline_accessors => 0,
79
80         @args,
81     );
82 }
83
84 sub create {
85     my ($self, $package_name, %options) = @_;
86
87     (ref $options{roles} eq 'ARRAY')
88         || $self->throw_error("You must pass an ARRAY ref of roles", data => $options{roles})
89             if exists $options{roles};
90     my $roles = delete $options{roles};
91
92     my $class = $self->SUPER::create($package_name, %options);
93
94     if ($roles) {
95         Moose::Util::apply_all_roles( $class, @$roles );
96     }
97
98     return $class;
99 }
100
101 sub _check_metaclass_compatibility {
102     my $self = shift;
103
104     if ( my @supers = $self->superclasses ) {
105         $self->_fix_metaclass_incompatibility(@supers);
106     }
107
108     $self->SUPER::_check_metaclass_compatibility(@_);
109 }
110
111 my %ANON_CLASSES;
112
113 sub create_anon_class {
114     my ($self, %options) = @_;
115
116     my $cache_ok = delete $options{cache};
117
118     # something like Super::Class|Super::Class::2=Role|Role::1
119     my $cache_key = join '=' => (
120         join('|', @{$options{superclasses} || []}),
121         join('|', sort @{$options{roles}   || []}),
122     );
123
124     if ($cache_ok && defined $ANON_CLASSES{$cache_key}) {
125         return $ANON_CLASSES{$cache_key};
126     }
127
128     my $new_class = $self->SUPER::create_anon_class(%options);
129
130     $ANON_CLASSES{$cache_key} = $new_class
131         if $cache_ok;
132
133     return $new_class;
134 }
135
136 sub add_role {
137     my ($self, $role) = @_;
138     (blessed($role) && $role->isa('Moose::Meta::Role'))
139         || $self->throw_error("Roles must be instances of Moose::Meta::Role", data => $role);
140     push @{$self->roles} => $role;
141 }
142
143 sub role_applications {
144     my ($self) = @_;
145
146     return @{$self->_get_role_applications};
147 }
148
149 sub add_role_application {
150     my ($self, $application) = @_;
151     (blessed($application) && $application->isa('Moose::Meta::Role::Application::ToClass'))
152         || $self->throw_error("Role applications must be instances of Moose::Meta::Role::Application::ToClass", data => $application);
153     push @{$self->_get_role_applications} => $application;
154 }
155
156 sub calculate_all_roles {
157     my $self = shift;
158     my %seen;
159     grep { !$seen{$_->name}++ } map { $_->calculate_all_roles } @{ $self->roles };
160 }
161
162 sub does_role {
163     my ($self, $role_name) = @_;
164
165     (defined $role_name)
166         || $self->throw_error("You must supply a role name to look for");
167
168     foreach my $class ($self->class_precedence_list) {
169         my $meta = Class::MOP::class_of($class);
170         # when a Moose metaclass is itself extended with a role,
171         # this check needs to be done since some items in the
172         # class_precedence_list might in fact be Class::MOP
173         # based still.
174         next unless $meta && $meta->can('roles');
175         foreach my $role (@{$meta->roles}) {
176             return 1 if $role->does_role($role_name);
177         }
178     }
179     return 0;
180 }
181
182 sub excludes_role {
183     my ($self, $role_name) = @_;
184
185     (defined $role_name)
186         || $self->throw_error("You must supply a role name to look for");
187
188     foreach my $class ($self->class_precedence_list) {
189         my $meta = Class::MOP::class_of($class);
190         # when a Moose metaclass is itself extended with a role,
191         # this check needs to be done since some items in the
192         # class_precedence_list might in fact be Class::MOP
193         # based still.
194         next unless $meta && $meta->can('roles');
195         foreach my $role (@{$meta->roles}) {
196             return 1 if $role->excludes_role($role_name);
197         }
198     }
199     return 0;
200 }
201
202 sub new_object {
203     my $class  = shift;
204     my $params = @_ == 1 ? $_[0] : {@_};
205     my $self   = $class->SUPER::new_object($params);
206
207     foreach my $attr ( $class->get_all_attributes() ) {
208
209         next unless $attr->can('has_trigger') && $attr->has_trigger;
210
211         my $init_arg = $attr->init_arg;
212
213         next unless defined $init_arg;
214
215         next unless exists $params->{$init_arg};
216
217         $attr->trigger->(
218             $self,
219             (
220                   $attr->should_coerce
221                 ? $attr->get_read_method_ref->($self)
222                 : $params->{$init_arg}
223             ),
224         );
225     }
226
227     return $self;
228 }
229
230 sub superclasses {
231     my $self = shift;
232     my @supers = @_;
233     foreach my $super (@supers) {
234         Class::MOP::load_class($super);
235         my $meta = Class::MOP::class_of($super);
236         Moose->throw_error("You cannot inherit from a Moose Role ($super)")
237             if $meta && $meta->isa('Moose::Meta::Role')
238     }
239     return $self->SUPER::superclasses(@supers);
240 }
241
242 ### ---------------------------------------------
243
244 sub add_attribute {
245     my $self = shift;
246     $self->SUPER::add_attribute(
247         (blessed $_[0] && $_[0]->isa('Class::MOP::Attribute')
248             ? $_[0]
249             : $self->_process_attribute(@_))
250     );
251 }
252
253 sub add_override_method_modifier {
254     my ($self, $name, $method, $_super_package) = @_;
255
256     (!$self->has_method($name))
257         || $self->throw_error("Cannot add an override method if a local method is already present");
258
259     $self->add_method($name => Moose::Meta::Method::Overridden->new(
260         method  => $method,
261         class   => $self,
262         package => $_super_package, # need this for roles
263         name    => $name,
264     ));
265 }
266
267 sub add_augment_method_modifier {
268     my ($self, $name, $method) = @_;
269     (!$self->has_method($name))
270         || $self->throw_error("Cannot add an augment method if a local method is already present");
271
272     $self->add_method($name => Moose::Meta::Method::Augmented->new(
273         method  => $method,
274         class   => $self,
275         name    => $name,
276     ));
277 }
278
279 ## Private Utility methods ...
280
281 sub _find_next_method_by_name_which_is_not_overridden {
282     my ($self, $name) = @_;
283     foreach my $method ($self->find_all_methods_by_name($name)) {
284         return $method->{code}
285             if blessed($method->{code}) && !$method->{code}->isa('Moose::Meta::Method::Overridden');
286     }
287     return undef;
288 }
289
290 sub _fix_metaclass_incompatibility {
291     my ($self, @superclasses) = @_;
292
293     foreach my $super (@superclasses) {
294         my $meta = Class::MOP::Class->initialize($super);
295
296         my @all_supers = $meta->linearized_isa;
297         shift @all_supers;
298
299         my @super_metas_to_fix = ($meta);
300
301         # We need to check & fix the immediate superclass. If its @ISA
302         # contains a class without a metaclass instance, followed by a
303         # class _with_ a metaclass instance, init a metaclass instance
304         # for classes without one and fix compat up to and including
305         # the class which was already initialized.
306         my $idx = first_index { Class::MOP::class_of($_) } @all_supers;
307
308         push @super_metas_to_fix,
309             map { Class::MOP::Class->initialize($_) } @all_supers[ 0 .. $idx ]
310             if $idx >= 0;
311
312         foreach my $super_meta (@super_metas_to_fix) {
313             $self->_fix_one_incompatible_metaclass($super_meta);
314         }
315     }
316 }
317
318 sub _fix_one_incompatible_metaclass {
319     my ($self, $meta) = @_;
320
321     return if $self->_superclass_meta_is_compatible($meta);
322
323     unless ( $self->is_pristine ) {
324         $self->throw_error(
325               "Cannot attempt to reinitialize metaclass for "
326             . $self->name
327             . ", it isn't pristine" );
328     }
329
330     $self->_reconcile_with_superclass_meta($meta);
331 }
332
333 sub _superclass_meta_is_compatible {
334     my ($self, $super_meta) = @_;
335
336     next unless $super_meta->isa("Class::MOP::Class");
337
338     my $super_meta_name
339         = $super_meta->is_immutable
340         ? $super_meta->get_mutable_metaclass_name
341         : ref($super_meta);
342
343     return 1
344         if $self->isa($super_meta_name)
345             and
346            $self->instance_metaclass->isa( $super_meta->instance_metaclass );
347 }
348
349 # I don't want to have to type this >1 time
350 my @MetaClassTypes =
351     qw( attribute_metaclass
352         method_metaclass
353         wrapped_method_metaclass
354         instance_metaclass
355         constructor_class
356         destructor_class
357         error_class );
358
359 sub _reconcile_with_superclass_meta {
360     my ($self, $super_meta) = @_;
361
362     my $super_meta_name
363         = $super_meta->is_immutable
364         ? $super_meta->get_mutable_metaclass_name
365         : ref($super_meta);
366
367     my $self_metaclass = ref $self;
368
369     # If neither of these is true we have a more serious
370     # incompatibility that we just cannot fix (yet?).
371     if ( $super_meta_name->isa( ref $self )
372         && all { $super_meta->$_->isa( $self->$_ ) } @MetaClassTypes ) {
373         $self->_reinitialize_with($super_meta);
374     }
375     elsif ( $self->_all_metaclasses_differ_by_roles_only($super_meta) ) {
376         $self->_reconcile_role_differences($super_meta);
377     }
378 }
379
380 sub _reinitialize_with {
381     my ( $self, $new_meta ) = @_;
382
383     my $new_self = $new_meta->reinitialize(
384         $self->name,
385         attribute_metaclass => $new_meta->attribute_metaclass,
386         method_metaclass    => $new_meta->method_metaclass,
387         instance_metaclass  => $new_meta->instance_metaclass,
388     );
389
390     $new_self->$_( $new_meta->$_ )
391         for qw( constructor_class destructor_class error_class );
392
393     %$self = %$new_self;
394
395     bless $self, ref $new_self;
396
397     # We need to replace the cached metaclass instance or else when it
398     # goes out of scope Class::MOP::Class destroy's the namespace for
399     # the metaclass's class, causing much havoc.
400     Class::MOP::store_metaclass_by_name( $self->name, $self );
401     Class::MOP::weaken_metaclass( $self->name ) if $self->is_anon_class;
402 }
403
404 # In the more complex case, we share a common ancestor with our
405 # superclass's metaclass, but each metaclass (ours and the parent's)
406 # has a different set of roles applied. We reconcile this by first
407 # reinitializing into the parent class, and _then_ applying our own
408 # roles.
409 sub _all_metaclasses_differ_by_roles_only {
410     my ($self, $super_meta) = @_;
411
412     for my $pair (
413         [ ref $self, ref $super_meta ],
414         map { [ $self->$_, $super_meta->$_ ] } @MetaClassTypes
415         ) {
416
417         next if $pair->[0] eq $pair->[1];
418
419         my $self_meta_meta  = Class::MOP::Class->initialize( $pair->[0] );
420         my $super_meta_meta = Class::MOP::Class->initialize( $pair->[1] );
421
422         my $common_ancestor
423             = _find_common_ancestor( $self_meta_meta, $super_meta_meta );
424
425         return unless $common_ancestor;
426
427         return
428             unless _is_role_only_subclass_of(
429             $self_meta_meta,
430             $common_ancestor,
431             )
432             && _is_role_only_subclass_of(
433             $super_meta_meta,
434             $common_ancestor,
435             );
436     }
437
438     return 1;
439 }
440
441 # This, and some other functions, could be called as methods, but
442 # they're not for two reasons. One, we just end up ignoring the first
443 # argument, because we can't call these directly on one of the real
444 # arguments, because one of them could be a Class::MOP::Class object
445 # and not a Moose::Meta::Class. Second, only a completely insane
446 # person would attempt to subclass this stuff!
447 sub _find_common_ancestor {
448     my ($meta1, $meta2) = @_;
449
450     # FIXME? This doesn't account for multiple inheritance (not sure
451     # if it needs to though). For example, is somewhere in $meta1's
452     # history it inherits from both ClassA and ClassB, and $meta2
453     # inherits from ClassB & ClassA, does it matter? And what crazy
454     # fool would do that anyway?
455
456     my %meta1_parents = map { $_ => 1 } $meta1->linearized_isa;
457
458     return first { $meta1_parents{$_} } $meta2->linearized_isa;
459 }
460
461 sub _is_role_only_subclass_of {
462     my ($meta, $ancestor) = @_;
463
464     return 1 if $meta->name eq $ancestor;
465
466     my @roles = _all_roles_until( $meta, $ancestor );
467
468     my %role_packages = map { $_->name => 1 } @roles;
469
470     my $ancestor_meta = Class::MOP::Class->initialize($ancestor);
471
472     my %shared_ancestors = map { $_ => 1 } $ancestor_meta->linearized_isa;
473
474     for my $method ( $meta->get_all_methods() ) {
475         next if $method->name eq 'meta';
476         next if $method->can('associated_attribute');
477
478         next
479             if $role_packages{ $method->original_package_name }
480                 || $shared_ancestors{ $method->original_package_name };
481
482         return 0;
483     }
484
485     # FIXME - this really isn't right. Just because an attribute is
486     # defined in a role doesn't mean it isn't _also_ defined in the
487     # subclass.
488     for my $attr ( $meta->get_all_attributes ) {
489         next if $shared_ancestors{ $attr->associated_class->name };
490
491         next if any { $_->has_attribute( $attr->name ) } @roles;
492
493         return 0;
494     }
495
496     return 1;
497 }
498
499 sub _all_roles {
500     my $meta = shift;
501
502     return _all_roles_until($meta);
503 }
504
505 sub _all_roles_until {
506     my ($meta, $stop_at_class) = @_;
507
508     return unless $meta->can('calculate_all_roles');
509
510     my @roles = $meta->calculate_all_roles;
511
512     for my $class ( $meta->linearized_isa ) {
513         last if $stop_at_class && $stop_at_class eq $class;
514
515         my $meta = Class::MOP::Class->initialize($class);
516         last unless $meta->can('calculate_all_roles');
517
518         push @roles, $meta->calculate_all_roles;
519     }
520
521     return uniq @roles;
522 }
523
524 sub _reconcile_role_differences {
525     my ($self, $super_meta) = @_;
526
527     my $self_meta = Class::MOP::class_of($self);
528
529     my %roles;
530
531     if ( my @roles = map { $_->name } _all_roles($self_meta) ) {
532         $roles{metaclass_roles} = \@roles;
533     }
534
535     for my $thing (@MetaClassTypes) {
536         my $name = $self->$thing();
537
538         my $thing_meta = Class::MOP::Class->initialize($name);
539
540         my @roles = map { $_->name } _all_roles($thing_meta)
541             or next;
542
543         $roles{ $thing . '_roles' } = \@roles;
544     }
545
546     $self->_reinitialize_with($super_meta);
547
548     Moose::Util::MetaRole::apply_metaclass_roles(
549         for_class => $self->name,
550         %roles,
551     );
552
553     return $self;
554 }
555
556 sub _process_attribute {
557     my ( $self, $name, @args ) = @_;
558
559     @args = %{$args[0]} if scalar @args == 1 && ref($args[0]) eq 'HASH';
560
561     if (($name || '') =~ /^\+(.*)/) {
562         return $self->_process_inherited_attribute($1, @args);
563     }
564     else {
565         return $self->_process_new_attribute($name, @args);
566     }
567 }
568
569 sub _process_new_attribute {
570     my ( $self, $name, @args ) = @_;
571
572     $self->attribute_metaclass->interpolate_class_and_new($name, @args);
573 }
574
575 sub _process_inherited_attribute {
576     my ($self, $attr_name, %options) = @_;
577     my $inherited_attr = $self->find_attribute_by_name($attr_name);
578     (defined $inherited_attr)
579         || $self->throw_error("Could not find an attribute by the name of '$attr_name' to inherit from in ${\$self->name}", data => $attr_name);
580     if ($inherited_attr->isa('Moose::Meta::Attribute')) {
581         return $inherited_attr->clone_and_inherit_options(%options);
582     }
583     else {
584         # NOTE:
585         # kind of a kludge to handle Class::MOP::Attributes
586         return $inherited_attr->Moose::Meta::Attribute::clone_and_inherit_options(%options);
587     }
588 }
589
590 ## -------------------------------------------------
591
592 our $error_level;
593
594 sub throw_error {
595     my ( $self, @args ) = @_;
596     local $error_level = ($error_level || 0) + 1;
597     $self->raise_error($self->create_error(@args));
598 }
599
600 sub raise_error {
601     my ( $self, @args ) = @_;
602     die @args;
603 }
604
605 sub create_error {
606     my ( $self, @args ) = @_;
607
608     require Carp::Heavy;
609
610     local $error_level = ($error_level || 0 ) + 1;
611
612     if ( @args % 2 == 1 ) {
613         unshift @args, "message";
614     }
615
616     my %args = ( metaclass => $self, last_error => $@, @args );
617
618     $args{depth} += $error_level;
619
620     my $class = ref $self ? $self->error_class : "Moose::Error::Default";
621
622     Class::MOP::load_class($class);
623
624     $class->new(
625         Carp::caller_info($args{depth}),
626         %args
627     );
628 }
629
630 1;
631
632 __END__
633
634 =pod
635
636 =head1 NAME
637
638 Moose::Meta::Class - The Moose metaclass
639
640 =head1 DESCRIPTION
641
642 This class is a subclass of L<Class::MOP::Class> that provides
643 additional Moose-specific functionality.
644
645 To really understand this class, you will need to start with the
646 L<Class::MOP::Class> documentation. This class can be understood as a
647 set of additional features on top of the basic feature provided by
648 that parent class.
649
650 =head1 INHERITANCE
651
652 C<Moose::Meta::Class> is a subclass of L<Class::MOP::Class>.
653
654 =head1 METHODS
655
656 =over 4
657
658 =item B<< Moose::Meta::Class->initialize($package_name, %options) >>
659
660 This overrides the parent's method in order to provide its own
661 defaults for the C<attribute_metaclass>, C<instance_metaclass>, and
662 C<method_metaclass> options.
663
664 These all default to the appropriate Moose class.
665
666 =item B<< Moose::Meta::Class->create($package_name, %options) >>
667
668 This overrides the parent's method in order to accept a C<roles>
669 option. This should be an array reference containing one more roles
670 that the class does.
671
672   my $metaclass = Moose::Meta::Class->create( 'New::Class', roles => [...] );
673
674 =item B<< Moose::Meta::Class->create_anon_class >>
675
676 This overrides the parent's method to accept a C<roles> option, just
677 as C<create> does.
678
679 It also accepts a C<cache> option. If this is true, then the anonymous
680 class will be cached based on its superclasses and roles. If an
681 existing anonymous class in the cache has the same superclasses and
682 roles, it will be reused.
683
684   my $metaclass = Moose::Meta::Class->create_anon_class(
685       superclasses => ['Foo'],
686       roles        => [qw/Some Roles Go Here/],
687       cache        => 1,
688   );
689
690 =item B<< $metaclass->make_immutable(%options) >>
691
692 This overrides the parent's method to add a few options. Specifically,
693 it uses the Moose-specific constructor and destructor classes, and
694 enables inlining the destructor.
695
696 Also, since Moose always inlines attributes, it sets the
697 C<inline_accessors> option to false.
698
699 =item B<< $metaclass->new_object(%params) >>
700
701 This overrides the parent's method in order to add support for
702 attribute triggers.
703
704 =item B<< $metaclass->add_override_method_modifier($name, $sub) >>
705
706 This adds an C<override> method modifier to the package.
707
708 =item B<< $metaclass->add_augment_method_modifier($name, $sub) >>
709
710 This adds an C<augment> method modifier to the package.
711
712 =item B<< $metaclass->calculate_all_roles >>
713
714 This will return a unique array of C<Moose::Meta::Role> instances
715 which are attached to this class.
716
717 =item B<< $metaclass->add_role($role) >>
718
719 This takes a L<Moose::Meta::Role> object, and adds it to the class's
720 list of roles. This I<does not> actually apply the role to the class.
721
722 =item B<< $metaclass->role_applications >>
723
724 Returns a list of L<Moose::Meta::Role::Application::ToClass>
725 objects, which contain the arguments to role application.
726
727 =item B<< $metaclass->add_role_application($application) >>
728
729 This takes a L<Moose::Meta::Role::Application::ToClass> object, and
730 adds it to the class's list of role applications. This I<does not>
731 actually apply any role to the class; it is only for tracking role
732 applications.
733
734 =item B<< $metaclass->does_role($role_name) >>
735
736 This returns a boolean indicating whether or not the class does the
737 specified role. This tests both the class and its parents.
738
739 =item B<< $metaclass->excludes_role($role_name) >>
740
741 A class excludes a role if it has already composed a role which
742 excludes the named role. This tests both the class and its parents.
743
744 =item B<< $metaclass->add_attribute($attr_name, %params|$params) >>
745
746 This overrides the parent's method in order to allow the parameters to
747 be provided as a hash reference.
748
749 =item B<< $metaclass->constructor_class ($class_name) >>
750
751 =item B<< $metaclass->destructor_class ($class_name) >>
752
753 These are the names of classes used when making a class
754 immutable. These default to L<Moose::Meta::Method::Constructor> and
755 L<Moose::Meta::Method::Destructor> respectively. These accessors are
756 read-write, so you can use them to change the class name.
757
758 =item B<< $metaclass->error_class($class_name) >>
759
760 The name of the class used to throw errors. This defaults to
761 L<Moose::Error::Default>, which generates an error with a stacktrace
762 just like C<Carp::confess>.
763
764 =item B<< $metaclass->throw_error($message, %extra) >>
765
766 Throws the error created by C<create_error> using C<raise_error>
767
768 =back
769
770 =head1 BUGS
771
772 All complex software has bugs lurking in it, and this module is no
773 exception. If you find a bug please either email me, or add the bug
774 to cpan-RT.
775
776 =head1 AUTHOR
777
778 Stevan Little E<lt>stevan@iinteractive.comE<gt>
779
780 =head1 COPYRIGHT AND LICENSE
781
782 Copyright 2006-2009 by Infinity Interactive, Inc.
783
784 L<http://www.iinteractive.com>
785
786 This library is free software; you can redistribute it and/or modify
787 it under the same terms as Perl itself.
788
789 =cut
790