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