Add built local::lib
[catagits/Gitalist.git] / local-lib5 / lib / perl5 / Moose / Meta / Class.pm
CommitLineData
3fea05b9 1
2package Moose::Meta::Class;
3
4use strict;
5use warnings;
6
7use Class::MOP;
8
9use Carp ();
10use List::Util qw( first );
11use List::MoreUtils qw( any all uniq first_index );
12use Scalar::Util 'weaken', 'blessed';
13
14our $VERSION = '0.93';
15$VERSION = eval $VERSION;
16our $AUTHORITY = 'cpan:STEVAN';
17
18use Moose::Meta::Method::Overridden;
19use Moose::Meta::Method::Augmented;
20use Moose::Error::Default;
21use Moose::Meta::Class::Immutable::Trait;
22use Moose::Meta::Method::Constructor;
23use Moose::Meta::Method::Destructor;
24
25use 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
59sub 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
71sub _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
84sub 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
101sub _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
111my %ANON_CLASSES;
112
113sub 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
136sub 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
143sub role_applications {
144 my ($self) = @_;
145
146 return @{$self->_get_role_applications};
147}
148
149sub 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
156sub calculate_all_roles {
157 my $self = shift;
158 my %seen;
159 grep { !$seen{$_->name}++ } map { $_->calculate_all_roles } @{ $self->roles };
160}
161
162sub 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
182sub 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
202sub 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
230sub 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 $self->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
244sub add_attribute {
245 my $self = shift;
246 my $attr =
247 (blessed $_[0] && $_[0]->isa('Class::MOP::Attribute')
248 ? $_[0]
249 : $self->_process_attribute(@_));
250 $self->SUPER::add_attribute($attr);
251 # it may be a Class::MOP::Attribute, theoretically, which doesn't have
252 # 'bare' and doesn't implement this method
253 if ($attr->can('_check_associated_methods')) {
254 $attr->_check_associated_methods;
255 }
256 return $attr;
257}
258
259sub add_override_method_modifier {
260 my ($self, $name, $method, $_super_package) = @_;
261
262 (!$self->has_method($name))
263 || $self->throw_error("Cannot add an override method if a local method is already present");
264
265 $self->add_method($name => Moose::Meta::Method::Overridden->new(
266 method => $method,
267 class => $self,
268 package => $_super_package, # need this for roles
269 name => $name,
270 ));
271}
272
273sub add_augment_method_modifier {
274 my ($self, $name, $method) = @_;
275 (!$self->has_method($name))
276 || $self->throw_error("Cannot add an augment method if a local method is already present");
277
278 $self->add_method($name => Moose::Meta::Method::Augmented->new(
279 method => $method,
280 class => $self,
281 name => $name,
282 ));
283}
284
285## Private Utility methods ...
286
287sub _find_next_method_by_name_which_is_not_overridden {
288 my ($self, $name) = @_;
289 foreach my $method ($self->find_all_methods_by_name($name)) {
290 return $method->{code}
291 if blessed($method->{code}) && !$method->{code}->isa('Moose::Meta::Method::Overridden');
292 }
293 return undef;
294}
295
296sub _fix_metaclass_incompatibility {
297 my ($self, @superclasses) = @_;
298
299 $self->_fix_one_incompatible_metaclass($_)
300 for map { Moose::Meta::Class->initialize($_) } @superclasses;
301}
302
303sub _fix_one_incompatible_metaclass {
304 my ($self, $meta) = @_;
305
306 return if $self->_superclass_meta_is_compatible($meta);
307
308 unless ( $self->is_pristine ) {
309 $self->throw_error(
310 "Cannot attempt to reinitialize metaclass for "
311 . $self->name
312 . ", it isn't pristine" );
313 }
314
315 $self->_reconcile_with_superclass_meta($meta);
316}
317
318sub _superclass_meta_is_compatible {
319 my ($self, $super_meta) = @_;
320
321 next unless $super_meta->isa("Class::MOP::Class");
322
323 my $super_meta_name
324 = $super_meta->is_immutable
325 ? $super_meta->_get_mutable_metaclass_name
326 : ref($super_meta);
327
328 return 1
329 if $self->isa($super_meta_name)
330 and
331 $self->instance_metaclass->isa( $super_meta->instance_metaclass );
332}
333
334# I don't want to have to type this >1 time
335my @MetaClassTypes =
336 qw( attribute_metaclass
337 method_metaclass
338 wrapped_method_metaclass
339 instance_metaclass
340 constructor_class
341 destructor_class
342 error_class );
343
344sub _reconcile_with_superclass_meta {
345 my ($self, $super_meta) = @_;
346
347 my $super_meta_name
348 = $super_meta->is_immutable
349 ? $super_meta->_get_mutable_metaclass_name
350 : ref($super_meta);
351
352 my $self_metaclass = ref $self;
353
354 # If neither of these is true we have a more serious
355 # incompatibility that we just cannot fix (yet?).
356 if ( $super_meta_name->isa( ref $self )
357 && all { $super_meta->$_->isa( $self->$_ ) } @MetaClassTypes ) {
358 $self->_reinitialize_with($super_meta);
359 }
360 elsif ( $self->_all_metaclasses_differ_by_roles_only($super_meta) ) {
361 $self->_reconcile_role_differences($super_meta);
362 }
363}
364
365sub _reinitialize_with {
366 my ( $self, $new_meta ) = @_;
367
368 my $new_self = $new_meta->reinitialize(
369 $self->name,
370 attribute_metaclass => $new_meta->attribute_metaclass,
371 method_metaclass => $new_meta->method_metaclass,
372 instance_metaclass => $new_meta->instance_metaclass,
373 );
374
375 $new_self->$_( $new_meta->$_ )
376 for qw( constructor_class destructor_class error_class );
377
378 %$self = %$new_self;
379
380 bless $self, ref $new_self;
381
382 # We need to replace the cached metaclass instance or else when it
383 # goes out of scope Class::MOP::Class destroy's the namespace for
384 # the metaclass's class, causing much havoc.
385 Class::MOP::store_metaclass_by_name( $self->name, $self );
386 Class::MOP::weaken_metaclass( $self->name ) if $self->is_anon_class;
387}
388
389# In the more complex case, we share a common ancestor with our
390# superclass's metaclass, but each metaclass (ours and the parent's)
391# has a different set of roles applied. We reconcile this by first
392# reinitializing into the parent class, and _then_ applying our own
393# roles.
394sub _all_metaclasses_differ_by_roles_only {
395 my ($self, $super_meta) = @_;
396
397 for my $pair (
398 [ ref $self, ref $super_meta ],
399 map { [ $self->$_, $super_meta->$_ ] } @MetaClassTypes
400 ) {
401
402 next if $pair->[0] eq $pair->[1];
403
404 my $self_meta_meta = Class::MOP::Class->initialize( $pair->[0] );
405 my $super_meta_meta = Class::MOP::Class->initialize( $pair->[1] );
406
407 my $common_ancestor
408 = _find_common_ancestor( $self_meta_meta, $super_meta_meta );
409
410 return unless $common_ancestor;
411
412 return
413 unless _is_role_only_subclass_of(
414 $self_meta_meta,
415 $common_ancestor,
416 )
417 && _is_role_only_subclass_of(
418 $super_meta_meta,
419 $common_ancestor,
420 );
421 }
422
423 return 1;
424}
425
426# This, and some other functions, could be called as methods, but
427# they're not for two reasons. One, we just end up ignoring the first
428# argument, because we can't call these directly on one of the real
429# arguments, because one of them could be a Class::MOP::Class object
430# and not a Moose::Meta::Class. Second, only a completely insane
431# person would attempt to subclass this stuff!
432sub _find_common_ancestor {
433 my ($meta1, $meta2) = @_;
434
435 # FIXME? This doesn't account for multiple inheritance (not sure
436 # if it needs to though). For example, is somewhere in $meta1's
437 # history it inherits from both ClassA and ClassB, and $meta2
438 # inherits from ClassB & ClassA, does it matter? And what crazy
439 # fool would do that anyway?
440
441 my %meta1_parents = map { $_ => 1 } $meta1->linearized_isa;
442
443 return first { $meta1_parents{$_} } $meta2->linearized_isa;
444}
445
446sub _is_role_only_subclass_of {
447 my ($meta, $ancestor) = @_;
448
449 return 1 if $meta->name eq $ancestor;
450
451 my @roles = _all_roles_until( $meta, $ancestor );
452
453 my %role_packages = map { $_->name => 1 } @roles;
454
455 my $ancestor_meta = Class::MOP::Class->initialize($ancestor);
456
457 my %shared_ancestors = map { $_ => 1 } $ancestor_meta->linearized_isa;
458
459 for my $method ( $meta->get_all_methods() ) {
460 next if $method->name eq 'meta';
461 next if $method->can('associated_attribute');
462
463 next
464 if $role_packages{ $method->original_package_name }
465 || $shared_ancestors{ $method->original_package_name };
466
467 return 0;
468 }
469
470 # FIXME - this really isn't right. Just because an attribute is
471 # defined in a role doesn't mean it isn't _also_ defined in the
472 # subclass.
473 for my $attr ( $meta->get_all_attributes ) {
474 next if $shared_ancestors{ $attr->associated_class->name };
475
476 next if any { $_->has_attribute( $attr->name ) } @roles;
477
478 return 0;
479 }
480
481 return 1;
482}
483
484sub _all_roles {
485 my $meta = shift;
486
487 return _all_roles_until($meta);
488}
489
490sub _all_roles_until {
491 my ($meta, $stop_at_class) = @_;
492
493 return unless $meta->can('calculate_all_roles');
494
495 my @roles = $meta->calculate_all_roles;
496
497 for my $class ( $meta->linearized_isa ) {
498 last if $stop_at_class && $stop_at_class eq $class;
499
500 my $meta = Class::MOP::Class->initialize($class);
501 last unless $meta->can('calculate_all_roles');
502
503 push @roles, $meta->calculate_all_roles;
504 }
505
506 return uniq @roles;
507}
508
509sub _reconcile_role_differences {
510 my ($self, $super_meta) = @_;
511
512 my $self_meta = Class::MOP::class_of($self);
513
514 my %roles;
515
516 if ( my @roles = map { $_->name } _all_roles($self_meta) ) {
517 $roles{metaclass_roles} = \@roles;
518 }
519
520 for my $thing (@MetaClassTypes) {
521 my $name = $self->$thing();
522
523 my $thing_meta = Class::MOP::Class->initialize($name);
524
525 my @roles = map { $_->name } _all_roles($thing_meta)
526 or next;
527
528 $roles{ $thing . '_roles' } = \@roles;
529 }
530
531 $self->_reinitialize_with($super_meta);
532
533 Moose::Util::MetaRole::apply_metaclass_roles(
534 for_class => $self->name,
535 %roles,
536 );
537
538 return $self;
539}
540
541sub _process_attribute {
542 my ( $self, $name, @args ) = @_;
543
544 @args = %{$args[0]} if scalar @args == 1 && ref($args[0]) eq 'HASH';
545
546 if (($name || '') =~ /^\+(.*)/) {
547 return $self->_process_inherited_attribute($1, @args);
548 }
549 else {
550 return $self->_process_new_attribute($name, @args);
551 }
552}
553
554sub _process_new_attribute {
555 my ( $self, $name, @args ) = @_;
556
557 $self->attribute_metaclass->interpolate_class_and_new($name, @args);
558}
559
560sub _process_inherited_attribute {
561 my ($self, $attr_name, %options) = @_;
562 my $inherited_attr = $self->find_attribute_by_name($attr_name);
563 (defined $inherited_attr)
564 || $self->throw_error("Could not find an attribute by the name of '$attr_name' to inherit from in ${\$self->name}", data => $attr_name);
565 if ($inherited_attr->isa('Moose::Meta::Attribute')) {
566 return $inherited_attr->clone_and_inherit_options(%options);
567 }
568 else {
569 # NOTE:
570 # kind of a kludge to handle Class::MOP::Attributes
571 return $inherited_attr->Moose::Meta::Attribute::clone_and_inherit_options(%options);
572 }
573}
574
575## -------------------------------------------------
576
577our $error_level;
578
579sub throw_error {
580 my ( $self, @args ) = @_;
581 local $error_level = ($error_level || 0) + 1;
582 $self->raise_error($self->create_error(@args));
583}
584
585sub raise_error {
586 my ( $self, @args ) = @_;
587 die @args;
588}
589
590sub create_error {
591 my ( $self, @args ) = @_;
592
593 require Carp::Heavy;
594
595 local $error_level = ($error_level || 0 ) + 1;
596
597 if ( @args % 2 == 1 ) {
598 unshift @args, "message";
599 }
600
601 my %args = ( metaclass => $self, last_error => $@, @args );
602
603 $args{depth} += $error_level;
604
605 my $class = ref $self ? $self->error_class : "Moose::Error::Default";
606
607 Class::MOP::load_class($class);
608
609 $class->new(
610 Carp::caller_info($args{depth}),
611 %args
612 );
613}
614
6151;
616
617__END__
618
619=pod
620
621=head1 NAME
622
623Moose::Meta::Class - The Moose metaclass
624
625=head1 DESCRIPTION
626
627This class is a subclass of L<Class::MOP::Class> that provides
628additional Moose-specific functionality.
629
630To really understand this class, you will need to start with the
631L<Class::MOP::Class> documentation. This class can be understood as a
632set of additional features on top of the basic feature provided by
633that parent class.
634
635=head1 INHERITANCE
636
637C<Moose::Meta::Class> is a subclass of L<Class::MOP::Class>.
638
639=head1 METHODS
640
641=over 4
642
643=item B<< Moose::Meta::Class->initialize($package_name, %options) >>
644
645This overrides the parent's method in order to provide its own
646defaults for the C<attribute_metaclass>, C<instance_metaclass>, and
647C<method_metaclass> options.
648
649These all default to the appropriate Moose class.
650
651=item B<< Moose::Meta::Class->create($package_name, %options) >>
652
653This overrides the parent's method in order to accept a C<roles>
654option. This should be an array reference containing roles
655that the class does, each optionally followed by a hashref of options
656(C<-excludes> and C<-alias>).
657
658 my $metaclass = Moose::Meta::Class->create( 'New::Class', roles => [...] );
659
660=item B<< Moose::Meta::Class->create_anon_class >>
661
662This overrides the parent's method to accept a C<roles> option, just
663as C<create> does.
664
665It also accepts a C<cache> option. If this is true, then the anonymous
666class will be cached based on its superclasses and roles. If an
667existing anonymous class in the cache has the same superclasses and
668roles, it will be reused.
669
670 my $metaclass = Moose::Meta::Class->create_anon_class(
671 superclasses => ['Foo'],
672 roles => [qw/Some Roles Go Here/],
673 cache => 1,
674 );
675
676=item B<< $metaclass->make_immutable(%options) >>
677
678This overrides the parent's method to add a few options. Specifically,
679it uses the Moose-specific constructor and destructor classes, and
680enables inlining the destructor.
681
682Also, since Moose always inlines attributes, it sets the
683C<inline_accessors> option to false.
684
685=item B<< $metaclass->new_object(%params) >>
686
687This overrides the parent's method in order to add support for
688attribute triggers.
689
690=item B<< $metaclass->add_override_method_modifier($name, $sub) >>
691
692This adds an C<override> method modifier to the package.
693
694=item B<< $metaclass->add_augment_method_modifier($name, $sub) >>
695
696This adds an C<augment> method modifier to the package.
697
698=item B<< $metaclass->calculate_all_roles >>
699
700This will return a unique array of C<Moose::Meta::Role> instances
701which are attached to this class.
702
703=item B<< $metaclass->add_role($role) >>
704
705This takes a L<Moose::Meta::Role> object, and adds it to the class's
706list of roles. This I<does not> actually apply the role to the class.
707
708=item B<< $metaclass->role_applications >>
709
710Returns a list of L<Moose::Meta::Role::Application::ToClass>
711objects, which contain the arguments to role application.
712
713=item B<< $metaclass->add_role_application($application) >>
714
715This takes a L<Moose::Meta::Role::Application::ToClass> object, and
716adds it to the class's list of role applications. This I<does not>
717actually apply any role to the class; it is only for tracking role
718applications.
719
720=item B<< $metaclass->does_role($role_name) >>
721
722This returns a boolean indicating whether or not the class does the
723specified role. This tests both the class and its parents.
724
725=item B<< $metaclass->excludes_role($role_name) >>
726
727A class excludes a role if it has already composed a role which
728excludes the named role. This tests both the class and its parents.
729
730=item B<< $metaclass->add_attribute($attr_name, %params|$params) >>
731
732This overrides the parent's method in order to allow the parameters to
733be provided as a hash reference.
734
735=item B<< $metaclass->constructor_class ($class_name) >>
736
737=item B<< $metaclass->destructor_class ($class_name) >>
738
739These are the names of classes used when making a class
740immutable. These default to L<Moose::Meta::Method::Constructor> and
741L<Moose::Meta::Method::Destructor> respectively. These accessors are
742read-write, so you can use them to change the class name.
743
744=item B<< $metaclass->error_class($class_name) >>
745
746The name of the class used to throw errors. This defaults to
747L<Moose::Error::Default>, which generates an error with a stacktrace
748just like C<Carp::confess>.
749
750=item B<< $metaclass->throw_error($message, %extra) >>
751
752Throws the error created by C<create_error> using C<raise_error>
753
754=back
755
756=head1 BUGS
757
758All complex software has bugs lurking in it, and this module is no
759exception. If you find a bug please either email me, or add the bug
760to cpan-RT.
761
762=head1 AUTHOR
763
764Stevan Little E<lt>stevan@iinteractive.comE<gt>
765
766=head1 COPYRIGHT AND LICENSE
767
768Copyright 2006-2009 by Infinity Interactive, Inc.
769
770L<http://www.iinteractive.com>
771
772This library is free software; you can redistribute it and/or modify
773it under the same terms as Perl itself.
774
775=cut
776