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