make _reconcile_roles_for_metaclass just return the metaclass name
[gitmo/Moose.git] / lib / Moose / Meta / Class.pm
CommitLineData
c0e30cf5 1
2package Moose::Meta::Class;
3
4use strict;
5use warnings;
6
0addec44 7use Class::MOP;
648e79ae 8
590e8894 9use Carp qw( confess );
2e7f6cf4 10use Data::OptList;
f8b6827f 11use List::Util qw( first );
349cda54 12use List::MoreUtils qw( any all uniq first_index );
21f1e231 13use Scalar::Util 'weaken', 'blessed';
a15dff8d 14
b6cca0d5 15our $VERSION = '1.14';
e606ae5f 16$VERSION = eval $VERSION;
d44714be 17our $AUTHORITY = 'cpan:STEVAN';
bc1e29b5 18
74862722 19use Moose::Meta::Method::Overridden;
3f9e4b0a 20use Moose::Meta::Method::Augmented;
77f14411 21use Moose::Error::Default;
0fa70d03 22use Moose::Meta::Class::Immutable::Trait;
23use Moose::Meta::Method::Constructor;
24use Moose::Meta::Method::Destructor;
8ee73eeb 25
c0e30cf5 26use base 'Class::MOP::Class';
27
598340d5 28__PACKAGE__->meta->add_attribute('roles' => (
ef333f17 29 reader => 'roles',
30 default => sub { [] }
31));
32
a9b63d79 33__PACKAGE__->meta->add_attribute('role_applications' => (
639f9a1a 34 reader => '_get_role_applications',
a9b63d79 35 default => sub { [] }
36));
37
0fa70d03 38__PACKAGE__->meta->add_attribute(
39 Class::MOP::Attribute->new('immutable_trait' => (
40 accessor => "immutable_trait",
41 default => 'Moose::Meta::Class::Immutable::Trait',
42 ))
43);
44
e606ae5f 45__PACKAGE__->meta->add_attribute('constructor_class' => (
46 accessor => 'constructor_class',
e0001338 47 default => 'Moose::Meta::Method::Constructor',
e606ae5f 48));
49
50__PACKAGE__->meta->add_attribute('destructor_class' => (
51 accessor => 'destructor_class',
e0001338 52 default => 'Moose::Meta::Method::Destructor',
e606ae5f 53));
54
11c86f15 55__PACKAGE__->meta->add_attribute('error_class' => (
bf6fa6b3 56 accessor => 'error_class',
57 default => 'Moose::Error::Default',
11c86f15 58));
59
590868a3 60sub initialize {
61 my $class = shift;
62 my $pkg = shift;
d03bd989 63 return Class::MOP::get_metaclass_by_name($pkg)
685f7e44 64 || $class->SUPER::initialize($pkg,
65 'attribute_metaclass' => 'Moose::Meta::Attribute',
66 'method_metaclass' => 'Moose::Meta::Method',
67 'instance_metaclass' => 'Moose::Meta::Instance',
68 @_
d03bd989 69 );
ac2dc464 70}
590868a3 71
61bdd94f 72sub create {
7d4035ae 73 my ($class, $package_name, %options) = @_;
d03bd989 74
61bdd94f 75 (ref $options{roles} eq 'ARRAY')
7d4035ae 76 || $class->throw_error("You must pass an ARRAY ref of roles", data => $options{roles})
61bdd94f 77 if exists $options{roles};
310ba883 78 my $roles = delete $options{roles};
dd37a5be 79
7d4035ae 80 my $new_meta = $class->SUPER::create($package_name, %options);
dd37a5be 81
310ba883 82 if ($roles) {
7d4035ae 83 Moose::Util::apply_all_roles( $new_meta, @$roles );
61bdd94f 84 }
d03bd989 85
7d4035ae 86 return $new_meta;
61bdd94f 87}
88
17594769 89my %ANON_CLASSES;
90
91sub create_anon_class {
92 my ($self, %options) = @_;
93
94 my $cache_ok = delete $options{cache};
d03bd989 95
cf600c83 96 my $cache_key
97 = _anon_cache_key( $options{superclasses}, $options{roles} );
d03bd989 98
6d5cbd2b 99 if ($cache_ok && defined $ANON_CLASSES{$cache_key}) {
17594769 100 return $ANON_CLASSES{$cache_key};
101 }
d03bd989 102
17594769 103 my $new_class = $self->SUPER::create_anon_class(%options);
104
6d5cbd2b 105 $ANON_CLASSES{$cache_key} = $new_class
106 if $cache_ok;
17594769 107
108 return $new_class;
109}
110
cf600c83 111sub _anon_cache_key {
112 # Makes something like Super::Class|Super::Class::2=Role|Role::1
113 return join '=' => (
114 join( '|', @{ $_[0] || [] } ),
115 join( '|', sort @{ $_[1] || [] } ),
116 );
117}
118
119sub reinitialize {
120 my $self = shift;
121 my $pkg = shift;
122
123 my $meta = blessed $pkg ? $pkg : Class::MOP::class_of($pkg);
124
125 my $cache_key;
126
127 my %existing_classes;
128 if ($meta) {
129 %existing_classes = map { $_ => $meta->$_() } qw(
130 attribute_metaclass
131 method_metaclass
132 wrapped_method_metaclass
133 instance_metaclass
134 constructor_class
135 destructor_class
136 error_class
137 );
138
139 $cache_key = _anon_cache_key(
140 [ $meta->superclasses ],
141 [ map { $_->name } @{ $meta->roles } ],
142 ) if $meta->is_anon_class;
143 }
144
145 my $new_meta = $self->SUPER::reinitialize(
146 $pkg,
147 %existing_classes,
148 @_,
149 );
150
151 return $new_meta unless defined $cache_key;
152
153 my $new_cache_key = _anon_cache_key(
154 [ $meta->superclasses ],
155 [ map { $_->name } @{ $meta->roles } ],
156 );
157
158 delete $ANON_CLASSES{$cache_key};
159 $ANON_CLASSES{$new_cache_key} = $new_meta;
160
161 return $new_meta;
162}
163
ef333f17 164sub add_role {
165 my ($self, $role) = @_;
166 (blessed($role) && $role->isa('Moose::Meta::Role'))
11c86f15 167 || $self->throw_error("Roles must be instances of Moose::Meta::Role", data => $role);
ef333f17 168 push @{$self->roles} => $role;
169}
170
639f9a1a 171sub role_applications {
172 my ($self) = @_;
173
174 return @{$self->_get_role_applications};
175}
176
a9b63d79 177sub add_role_application {
178 my ($self, $application) = @_;
179 (blessed($application) && $application->isa('Moose::Meta::Role::Application::ToClass'))
180 || $self->throw_error("Role applications must be instances of Moose::Meta::Role::Application::ToClass", data => $application);
639f9a1a 181 push @{$self->_get_role_applications} => $application;
a9b63d79 182}
183
b8aeb4dc 184sub calculate_all_roles {
185 my $self = shift;
186 my %seen;
187 grep { !$seen{$_->name}++ } map { $_->calculate_all_roles } @{ $self->roles };
188}
189
9f83eb5d 190sub calculate_all_roles_with_inheritance {
191 my $self = shift;
192 my %seen;
193 grep { !$seen{$_->name}++ }
194 map { Class::MOP::class_of($_)->can('calculate_all_roles')
195 ? Class::MOP::class_of($_)->calculate_all_roles
196 : () }
197 $self->linearized_isa;
198}
199
ef333f17 200sub does_role {
201 my ($self, $role_name) = @_;
322abb07 202
ef333f17 203 (defined $role_name)
11c86f15 204 || $self->throw_error("You must supply a role name to look for");
322abb07 205
9c429218 206 foreach my $class ($self->class_precedence_list) {
322abb07 207 my $meta = Class::MOP::class_of($class);
3d0f5a27 208 # when a Moose metaclass is itself extended with a role,
209 # this check needs to be done since some items in the
210 # class_precedence_list might in fact be Class::MOP
211 # based still.
322abb07 212 next unless $meta && $meta->can('roles');
213 foreach my $role (@{$meta->roles}) {
9c429218 214 return 1 if $role->does_role($role_name);
215 }
ef333f17 216 }
217 return 0;
218}
219
d79e62fd 220sub excludes_role {
221 my ($self, $role_name) = @_;
ebfc4d0f 222
d79e62fd 223 (defined $role_name)
11c86f15 224 || $self->throw_error("You must supply a role name to look for");
ebfc4d0f 225
ac2dc464 226 foreach my $class ($self->class_precedence_list) {
ebfc4d0f 227 my $meta = Class::MOP::class_of($class);
228 # when a Moose metaclass is itself extended with a role,
229 # this check needs to be done since some items in the
230 # class_precedence_list might in fact be Class::MOP
231 # based still.
232 next unless $meta && $meta->can('roles');
233 foreach my $role (@{$meta->roles}) {
9c429218 234 return 1 if $role->excludes_role($role_name);
235 }
d79e62fd 236 }
237 return 0;
238}
239
8c9d74e7 240sub new_object {
7d4035ae 241 my $self = shift;
e606ae5f 242 my $params = @_ == 1 ? $_[0] : {@_};
7d4035ae 243 my $object = $self->SUPER::new_object($params);
1308deb4 244
7d4035ae 245 foreach my $attr ( $self->get_all_attributes() ) {
1308deb4 246
247 next unless $attr->can('has_trigger') && $attr->has_trigger;
248
249 my $init_arg = $attr->init_arg;
250
251 next unless defined $init_arg;
252
253 next unless exists $params->{$init_arg};
254
255 $attr->trigger->(
7d4035ae 256 $object,
1308deb4 257 (
258 $attr->should_coerce
7d4035ae 259 ? $attr->get_read_method_ref->($object)
1308deb4 260 : $params->{$init_arg}
261 ),
1308deb4 262 );
8c9d74e7 263 }
1308deb4 264
7d4035ae 265 $object->BUILDALL($params) if $object->can('BUILDALL');
a19ae3d7 266
7d4035ae 267 return $object;
8c9d74e7 268}
269
e2eef3a5 270sub superclasses {
271 my $self = shift;
2e7f6cf4 272 my $supers = Data::OptList::mkopt(\@_);
273 foreach my $super (@{ $supers }) {
274 my ($name, $opts) = @{ $super };
275 Class::MOP::load_class($name, $opts);
276 my $meta = Class::MOP::class_of($name);
277 $self->throw_error("You cannot inherit from a Moose Role ($name)")
e2eef3a5 278 if $meta && $meta->isa('Moose::Meta::Role')
279 }
2e7f6cf4 280 return $self->SUPER::superclasses(map { $_->[0] } @{ $supers });
e2eef3a5 281}
282
093b12c2 283### ---------------------------------------------
284
a2eec5e7 285sub add_attribute {
286 my $self = shift;
28af3424 287 my $attr =
e472c9a5 288 (blessed $_[0] && $_[0]->isa('Class::MOP::Attribute')
d03bd989 289 ? $_[0]
28af3424 290 : $self->_process_attribute(@_));
291 $self->SUPER::add_attribute($attr);
292 # it may be a Class::MOP::Attribute, theoretically, which doesn't have
293 # 'bare' and doesn't implement this method
9340e346 294 if ($attr->can('_check_associated_methods')) {
295 $attr->_check_associated_methods;
28af3424 296 }
297 return $attr;
a2eec5e7 298}
299
78cd1d3b 300sub add_override_method_modifier {
301 my ($self, $name, $method, $_super_package) = @_;
18c2ec0e 302
d05cd563 303 (!$self->has_method($name))
11c86f15 304 || $self->throw_error("Cannot add an override method if a local method is already present");
18c2ec0e 305
74862722 306 $self->add_method($name => Moose::Meta::Method::Overridden->new(
3f9e4b0a 307 method => $method,
308 class => $self,
309 package => $_super_package, # need this for roles
310 name => $name,
18c2ec0e 311 ));
78cd1d3b 312}
313
314sub add_augment_method_modifier {
ac2dc464 315 my ($self, $name, $method) = @_;
d05cd563 316 (!$self->has_method($name))
11c86f15 317 || $self->throw_error("Cannot add an augment method if a local method is already present");
3f9e4b0a 318
319 $self->add_method($name => Moose::Meta::Method::Augmented->new(
320 method => $method,
321 class => $self,
322 name => $name,
323 ));
78cd1d3b 324}
325
1341f10c 326## Private Utility methods ...
327
05d9eaf6 328sub _find_next_method_by_name_which_is_not_overridden {
329 my ($self, $name) = @_;
68efb014 330 foreach my $method ($self->find_all_methods_by_name($name)) {
ac2dc464 331 return $method->{code}
74862722 332 if blessed($method->{code}) && !$method->{code}->isa('Moose::Meta::Method::Overridden');
05d9eaf6 333 }
334 return undef;
335}
336
f6df97ae 337## Metaclass compatibility
f8b6827f 338
f6df97ae 339sub _base_metaclasses {
340 my $self = shift;
341 my %metaclasses = $self->SUPER::_base_metaclasses;
342 for my $class (keys %metaclasses) {
343 $metaclasses{$class} =~ s/^Class::MOP/Moose::Meta/;
1341f10c 344 }
f6df97ae 345 return (
346 %metaclasses,
347 error_class => 'Moose::Error::Default',
f8b6827f 348 );
f8b6827f 349}
350
6524ca01 351sub _can_fix_metaclass_incompatibility {
352 my $self = shift;
353 return 1 if $self->_can_fix_metaclass_incompatibility_by_role_reconciliation(@_);
354 return $self->SUPER::_can_fix_metaclass_incompatibility(@_);
355}
356
357sub _can_fix_metaclass_incompatibility_by_role_reconciliation {
358 my $self = shift;
359 my ($super_meta) = @_;
360
361 return 1 if $self->_can_fix_class_metaclass_incompatibility_by_role_reconciliation($super_meta);
362
363 my %base_metaclass = $self->_base_metaclasses;
364 for my $metaclass_type (keys %base_metaclass) {
365 next unless defined $self->$metaclass_type;
366 return 1 if $self->_can_fix_single_metaclass_incompatibility_by_role_reconciliation($metaclass_type, $super_meta);
367 }
368
369 return;
370}
371
372sub _can_fix_class_metaclass_incompatibility_by_role_reconciliation {
373 my $self = shift;
374 my ($super_meta) = @_;
375
376 my $super_meta_name = $super_meta->_real_ref_name;
377
378 return $self->_classes_differ_by_roles_only(
379 blessed($self),
380 $super_meta_name,
381 'Moose::Meta::Class',
382 );
383}
384
385sub _can_fix_single_metaclass_incompatibility_by_role_reconciliation {
386 my $self = shift;
387 my ($metaclass_type, $super_meta) = @_;
388
389 my $class_specific_meta_name = $self->$metaclass_type;
390 return unless $super_meta->can($metaclass_type);
391 my $super_specific_meta_name = $super_meta->$metaclass_type;
392 my %metaclasses = $self->_base_metaclasses;
393
394 return $self->_classes_differ_by_roles_only(
395 $class_specific_meta_name,
396 $super_specific_meta_name,
397 $metaclasses{$metaclass_type},
398 );
399}
400
401sub _classes_differ_by_roles_only {
402 my $self = shift;
403 my ( $self_meta_name, $super_meta_name, $expected_ancestor ) = @_;
404
405 my $common_base_name
406 = $self->_find_common_base( $self_meta_name, $super_meta_name );
407
408 # If they're not both moose metaclasses, and the cmop fixing couldn't do
409 # anything, there's nothing more we can do. The $expected_ancestor should
410 # always be a Moose metaclass name like Moose::Meta::Class or
411 # Moose::Meta::Attribute.
412 return unless defined $common_base_name;
413 return unless $common_base_name->isa($expected_ancestor);
414
415 my @super_meta_name_ancestor_names
416 = $self->_get_ancestors_until( $super_meta_name, $common_base_name );
417 my @class_meta_name_ancestor_names
418 = $self->_get_ancestors_until( $self_meta_name, $common_base_name );
419
420 return
421 unless all { $self->_is_role_only_subclass($_) }
422 @super_meta_name_ancestor_names,
423 @class_meta_name_ancestor_names;
424
425 return 1;
426}
427
f6df97ae 428sub _find_common_base {
429 my $self = shift;
430 my ($meta1, $meta2) = map { Class::MOP::class_of($_) } @_;
0b91067b 431 return unless defined $meta1 && defined $meta2;
f8b6827f 432
433 # FIXME? This doesn't account for multiple inheritance (not sure
79ca665e 434 # if it needs to though). For example, if somewhere in $meta1's
db9fda52 435 # history it inherits from both ClassA and ClassB, and $meta2
f8b6827f 436 # inherits from ClassB & ClassA, does it matter? And what crazy
437 # fool would do that anyway?
438
439 my %meta1_parents = map { $_ => 1 } $meta1->linearized_isa;
440
441 return first { $meta1_parents{$_} } $meta2->linearized_isa;
442}
443
f6df97ae 444sub _get_ancestors_until {
445 my $self = shift;
dd3ac8f9 446 my ($start_name, $until_name) = @_;
f8b6827f 447
dd3ac8f9 448 my @ancestor_names;
449 for my $ancestor_name (Class::MOP::class_of($start_name)->linearized_isa) {
450 last if $ancestor_name eq $until_name;
451 push @ancestor_names, $ancestor_name;
f6df97ae 452 }
dd3ac8f9 453 return @ancestor_names;
f6df97ae 454}
f8b6827f 455
f6df97ae 456sub _is_role_only_subclass {
457 my $self = shift;
dd3ac8f9 458 my ($meta_name) = @_;
459 my $meta = Class::MOP::Class->initialize($meta_name);
460 my @parent_names = $meta->superclasses;
f6df97ae 461
462 # XXX: don't feel like messing with multiple inheritance here... what would
463 # that even do?
dd3ac8f9 464 return unless @parent_names == 1;
465 my ($parent_name) = @parent_names;
466 my $parent_meta = Class::MOP::Class->initialize($parent_name);
f6df97ae 467
593152a0 468 my @roles = $meta->can('calculate_all_roles_with_inheritance')
469 ? $meta->calculate_all_roles_with_inheritance
470 : ();
471
f6df97ae 472 # loop over all methods that are a part of the current class
473 # (not inherited)
723576c6 474 for my $method ( $meta->_get_local_methods ) {
f6df97ae 475 # always ignore meta
f8b6827f 476 next if $method->name eq 'meta';
f6df97ae 477 # we'll deal with attributes below
593152a0 478 next if $method->can('associated_attribute');
f6df97ae 479 # if the method comes from a role we consumed, ignore it
dd3ac8f9 480 next if $meta->can('does_role')
481 && $meta->does_role($method->original_package_name);
593152a0 482 # FIXME - this really isn't right. Just because a modifier is
483 # defined in a role doesn't mean it isn't _also_ defined in the
484 # subclass.
485 next if $method->isa('Class::MOP::Method::Wrapped')
486 && (
487 (!scalar($method->around_modifiers)
488 || any { $_->has_around_method_modifiers($method->name) } @roles)
489 && (!scalar($method->before_modifiers)
490 || any { $_->has_before_method_modifiers($method->name) } @roles)
491 && (!scalar($method->after_modifiers)
492 || any { $_->has_after_method_modifiers($method->name) } @roles)
493 );
f8b6827f 494
495 return 0;
496 }
497
f6df97ae 498 # loop over all attributes that are a part of the current class
499 # (not inherited)
f8b6827f 500 # FIXME - this really isn't right. Just because an attribute is
501 # defined in a role doesn't mean it isn't _also_ defined in the
502 # subclass.
dd3ac8f9 503 for my $attr (map { $meta->get_attribute($_) } $meta->get_attribute_list) {
593152a0 504 next if any { $_->has_attribute($attr->name) } @roles;
f8b6827f 505
506 return 0;
507 }
508
509 return 1;
510}
511
f6df97ae 512sub _fix_class_metaclass_incompatibility {
513 my $self = shift;
514 my ($super_meta) = @_;
f8b6827f 515
f6df97ae 516 $self->SUPER::_fix_class_metaclass_incompatibility(@_);
f8b6827f 517
f6df97ae 518 if ($self->_can_fix_class_metaclass_incompatibility_by_role_reconciliation($super_meta)) {
590e8894 519 ($self->is_pristine)
520 || confess "Can't fix metaclass incompatibility for "
521 . $self->name
522 . " because it is not pristine.";
a907317a 523 my $super_meta_name = $super_meta->_real_ref_name;
8450b001 524 my $class_meta_subclass_meta_name = $self->_reconcile_roles_for_metaclass(blessed($self), $super_meta_name);
525 my $new_self = $class_meta_subclass_meta_name->reinitialize(
cf7febc7 526 $self->name,
527 );
6a52b083 528
8450b001 529 $self->_replace_self( $new_self, $class_meta_subclass_meta_name );
f8b6827f 530 }
f6df97ae 531}
f8b6827f 532
f6df97ae 533sub _fix_single_metaclass_incompatibility {
534 my $self = shift;
535 my ($metaclass_type, $super_meta) = @_;
f8b6827f 536
f6df97ae 537 $self->SUPER::_fix_single_metaclass_incompatibility(@_);
f8b6827f 538
f6df97ae 539 if ($self->_can_fix_single_metaclass_incompatibility_by_role_reconciliation($metaclass_type, $super_meta)) {
590e8894 540 ($self->is_pristine)
541 || confess "Can't fix metaclass incompatibility for "
542 . $self->name
543 . " because it is not pristine.";
7f6c8567 544 my $super_meta_name = $super_meta->_real_ref_name;
8450b001 545 my $class_specific_meta_subclass_meta_name = $self->_reconcile_roles_for_metaclass($self->$metaclass_type, $super_meta->$metaclass_type);
cf7febc7 546 my $new_self = $super_meta->reinitialize(
547 $self->name,
8450b001 548 $metaclass_type => $class_specific_meta_subclass_meta_name,
cf7febc7 549 );
6a52b083 550
7f6c8567 551 $self->_replace_self( $new_self, $super_meta_name );
f6df97ae 552 }
f8b6827f 553}
554
6524ca01 555sub _reconcile_roles_for_metaclass {
556 my $self = shift;
557 my ($class_meta_name, $super_meta_name) = @_;
558
559 my @role_differences = $self->_role_differences(
560 $class_meta_name, $super_meta_name,
561 );
562
563 # handle the case where we need to fix compatibility between a class and
564 # its parent, but all roles in the class are already also done by the
565 # parent
566 # see t/050/054.t
8450b001 567 return $super_meta_name
6524ca01 568 unless @role_differences;
569
570 return Moose::Meta::Class->create_anon_class(
571 superclasses => [$super_meta_name],
572 roles => [map { $_->name } @role_differences],
573 cache => 1,
8450b001 574 )->name;
6524ca01 575}
576
577sub _role_differences {
578 my $self = shift;
579 my ($class_meta_name, $super_meta_name) = @_;
580 my @super_role_metas = $super_meta_name->meta->can('calculate_all_roles_with_inheritance')
581 ? $super_meta_name->meta->calculate_all_roles_with_inheritance
582 : ();
583 my @role_metas = $class_meta_name->meta->can('calculate_all_roles_with_inheritance')
584 ? $class_meta_name->meta->calculate_all_roles_with_inheritance
585 : ();
586 my @differences;
587 for my $role_meta (@role_metas) {
588 push @differences, $role_meta
589 unless any { $_->name eq $role_meta->name } @super_role_metas;
590 }
591 return @differences;
592}
6a52b083 593
594sub _replace_self {
595 my $self = shift;
596 my ( $new_self, $new_class) = @_;
597
598 %$self = %$new_self;
599 bless $self, $new_class;
600
601 # We need to replace the cached metaclass instance or else when it goes
602 # out of scope Class::MOP::Class destroy's the namespace for the
603 # metaclass's class, causing much havoc.
604 Class::MOP::store_metaclass_by_name( $self->name, $self );
605 Class::MOP::weaken_metaclass( $self->name ) if $self->is_anon_class;
606}
607
6524ca01 608sub _get_compatible_single_metaclass {
609 my $self = shift;
610
611 return $self->SUPER::_get_compatible_single_metaclass(@_)
612 || $self->_get_compatible_single_metaclass_by_role_reconciliation(@_);
613}
614
c1f0275a 615sub _get_compatible_single_metaclass_by_role_reconciliation {
616 my $self = shift;
617 my ($single_meta_name) = @_;
618
619 my $current_single_meta_name = $self->_get_associated_single_metaclass($single_meta_name);
620
8450b001 621 return $self->_reconcile_roles_for_metaclass($single_meta_name, $current_single_meta_name);
c1f0275a 622}
623
1341f10c 624sub _process_attribute {
a3738e5b 625 my ( $self, $name, @args ) = @_;
7e59b803 626
627 @args = %{$args[0]} if scalar @args == 1 && ref($args[0]) eq 'HASH';
d9bb6c63 628
f9b5f5f8 629 if (($name || '') =~ /^\+(.*)/) {
7e59b803 630 return $self->_process_inherited_attribute($1, @args);
1341f10c 631 }
632 else {
7e59b803 633 return $self->_process_new_attribute($name, @args);
634 }
635}
636
637sub _process_new_attribute {
638 my ( $self, $name, @args ) = @_;
7e59b803 639
d5c30e52 640 $self->attribute_metaclass->interpolate_class_and_new($name, @args);
1341f10c 641}
642
643sub _process_inherited_attribute {
644 my ($self, $attr_name, %options) = @_;
645 my $inherited_attr = $self->find_attribute_by_name($attr_name);
646 (defined $inherited_attr)
329c5dd4 647 || $self->throw_error("Could not find an attribute by the name of '$attr_name' to inherit from in ${\$self->name}", data => $attr_name);
1341f10c 648 if ($inherited_attr->isa('Moose::Meta::Attribute')) {
d7d8a8c7 649 return $inherited_attr->clone_and_inherit_options(%options);
1341f10c 650 }
651 else {
652 # NOTE:
653 # kind of a kludge to handle Class::MOP::Attributes
d7d8a8c7 654 return $inherited_attr->Moose::Meta::Attribute::clone_and_inherit_options(%options);
ac2dc464 655 }
1341f10c 656}
657
948cd189 658## Immutability
659
660sub _immutable_options {
661 my ( $self, @args ) = @_;
662
663 $self->SUPER::_immutable_options(
664 inline_destructor => 1,
948cd189 665
666 # Moose always does this when an attribute is created
667 inline_accessors => 0,
668
669 @args,
670 );
671}
672
5cf3dbcf 673## -------------------------------------------------
674
bf6fa6b3 675our $error_level;
11c86f15 676
677sub throw_error {
678 my ( $self, @args ) = @_;
bf6fa6b3 679 local $error_level = ($error_level || 0) + 1;
11c86f15 680 $self->raise_error($self->create_error(@args));
681}
682
683sub raise_error {
684 my ( $self, @args ) = @_;
685 die @args;
686}
687
688sub create_error {
689 my ( $self, @args ) = @_;
690
18748ad6 691 require Carp::Heavy;
692
bf6fa6b3 693 local $error_level = ($error_level || 0 ) + 1;
18748ad6 694
11c86f15 695 if ( @args % 2 == 1 ) {
696 unshift @args, "message";
697 }
698
fcab1742 699 my %args = ( metaclass => $self, last_error => $@, @args );
11c86f15 700
bf6fa6b3 701 $args{depth} += $error_level;
11c86f15 702
bf6fa6b3 703 my $class = ref $self ? $self->error_class : "Moose::Error::Default";
11c86f15 704
a810a01f 705 Class::MOP::load_class($class);
706
11c86f15 707 $class->new(
bf6fa6b3 708 Carp::caller_info($args{depth}),
709 %args
11c86f15 710 );
711}
712
c0e30cf5 7131;
714
715__END__
716
717=pod
718
719=head1 NAME
720
e522431d 721Moose::Meta::Class - The Moose metaclass
c0e30cf5 722
c0e30cf5 723=head1 DESCRIPTION
724
70bb0f97 725This class is a subclass of L<Class::MOP::Class> that provides
726additional Moose-specific functionality.
e522431d 727
7854b409 728To really understand this class, you will need to start with the
729L<Class::MOP::Class> documentation. This class can be understood as a
730set of additional features on top of the basic feature provided by
731that parent class.
6ba6d68c 732
d4b1449e 733=head1 INHERITANCE
734
735C<Moose::Meta::Class> is a subclass of L<Class::MOP::Class>.
736
c0e30cf5 737=head1 METHODS
738
739=over 4
740
70bb0f97 741=item B<< Moose::Meta::Class->initialize($package_name, %options) >>
590868a3 742
70bb0f97 743This overrides the parent's method in order to provide its own
744defaults for the C<attribute_metaclass>, C<instance_metaclass>, and
745C<method_metaclass> options.
61bdd94f 746
70bb0f97 747These all default to the appropriate Moose class.
61bdd94f 748
70bb0f97 749=item B<< Moose::Meta::Class->create($package_name, %options) >>
17594769 750
70bb0f97 751This overrides the parent's method in order to accept a C<roles>
9e25a72a 752option. This should be an array reference containing roles
753that the class does, each optionally followed by a hashref of options
754(C<-excludes> and C<-alias>).
17594769 755
70bb0f97 756 my $metaclass = Moose::Meta::Class->create( 'New::Class', roles => [...] );
17594769 757
70bb0f97 758=item B<< Moose::Meta::Class->create_anon_class >>
17594769 759
70bb0f97 760This overrides the parent's method to accept a C<roles> option, just
761as C<create> does.
5cf3dbcf 762
70bb0f97 763It also accepts a C<cache> option. If this is true, then the anonymous
764class will be cached based on its superclasses and roles. If an
765existing anonymous class in the cache has the same superclasses and
766roles, it will be reused.
ac2dc464 767
70bb0f97 768 my $metaclass = Moose::Meta::Class->create_anon_class(
769 superclasses => ['Foo'],
770 roles => [qw/Some Roles Go Here/],
771 cache => 1,
772 );
ac2dc464 773
2e7f6cf4 774Each entry in both the C<superclasses> and the C<roles> option can be
b2d54db8 775followed by a hash reference with arguments. The C<superclasses>
2e7f6cf4 776option can be supplied with a L<-version|Class::MOP/Class Loading
777Options> option that ensures the loaded superclass satisfies the
778required version. The C<role> option also takes the C<-version> as an
779argument, but the option hash reference can also contain any other
780role relevant values like exclusions or parameterized role arguments.
781
70bb0f97 782=item B<< $metaclass->make_immutable(%options) >>
ac2dc464 783
70bb0f97 784This overrides the parent's method to add a few options. Specifically,
785it uses the Moose-specific constructor and destructor classes, and
786enables inlining the destructor.
8c9d74e7 787
dcdceb38 788Since Moose always inlines attributes, it sets the C<inline_accessors> option
789to false.
790
70bb0f97 791=item B<< $metaclass->new_object(%params) >>
a15dff8d 792
70bb0f97 793This overrides the parent's method in order to add support for
794attribute triggers.
6ba6d68c 795
2e7f6cf4 796=item B<< $metaclass->superclasses(@superclasses) >>
797
6b958a3e 798This is the accessor allowing you to read or change the parents of
2e7f6cf4 799the class.
800
801Each superclass can be followed by a hash reference containing a
802L<-version|Class::MOP/Class Loading Options> value. If the version
803requirement is not satisfied an error will be thrown.
804
70bb0f97 805=item B<< $metaclass->add_override_method_modifier($name, $sub) >>
ef1d5f4b 806
70bb0f97 807This adds an C<override> method modifier to the package.
e9ec68d6 808
70bb0f97 809=item B<< $metaclass->add_augment_method_modifier($name, $sub) >>
e9ec68d6 810
70bb0f97 811This adds an C<augment> method modifier to the package.
78cd1d3b 812
70bb0f97 813=item B<< $metaclass->calculate_all_roles >>
02a0fb52 814
70bb0f97 815This will return a unique array of C<Moose::Meta::Role> instances
816which are attached to this class.
78cd1d3b 817
9f83eb5d 818=item B<< $metaclass->calculate_all_roles_with_inheritance >>
819
820This will return a unique array of C<Moose::Meta::Role> instances
821which are attached to this class, and each of this class's ancestors.
822
70bb0f97 823=item B<< $metaclass->add_role($role) >>
02a0fb52 824
70bb0f97 825This takes a L<Moose::Meta::Role> object, and adds it to the class's
826list of roles. This I<does not> actually apply the role to the class.
2b14ac61 827
b90dd4ef 828=item B<< $metaclass->role_applications >>
829
639f9a1a 830Returns a list of L<Moose::Meta::Role::Application::ToClass>
b90dd4ef 831objects, which contain the arguments to role application.
832
833=item B<< $metaclass->add_role_application($application) >>
834
835This takes a L<Moose::Meta::Role::Application::ToClass> object, and
836adds it to the class's list of role applications. This I<does not>
837actually apply any role to the class; it is only for tracking role
838applications.
839
560c498d 840=item B<< $metaclass->does_role($role) >>
ef333f17 841
560c498d 842This returns a boolean indicating whether or not the class does the specified
843role. The role provided can be either a role name or a L<Moose::Meta::Role>
844object. This tests both the class and its parents.
02a0fb52 845
70bb0f97 846=item B<< $metaclass->excludes_role($role_name) >>
ef333f17 847
70bb0f97 848A class excludes a role if it has already composed a role which
849excludes the named role. This tests both the class and its parents.
02a0fb52 850
70bb0f97 851=item B<< $metaclass->add_attribute($attr_name, %params|$params) >>
ef333f17 852
70bb0f97 853This overrides the parent's method in order to allow the parameters to
854be provided as a hash reference.
02a0fb52 855
9f9fdd08 856=item B<< $metaclass->constructor_class($class_name) >>
d79e62fd 857
9f9fdd08 858=item B<< $metaclass->destructor_class($class_name) >>
e606ae5f 859
948cd189 860These are the names of classes used when making a class immutable. These
90a49845 861default to L<Moose::Meta::Method::Constructor> and
862L<Moose::Meta::Method::Destructor> respectively. These accessors are
863read-write, so you can use them to change the class name.
e606ae5f 864
70bb0f97 865=item B<< $metaclass->error_class($class_name) >>
8b1d510f 866
70bb0f97 867The name of the class used to throw errors. This defaults to
8b1d510f 868L<Moose::Error::Default>, which generates an error with a stacktrace
869just like C<Carp::confess>.
870
70bb0f97 871=item B<< $metaclass->throw_error($message, %extra) >>
11c86f15 872
873Throws the error created by C<create_error> using C<raise_error>
874
c0e30cf5 875=back
876
877=head1 BUGS
878
d4048ef3 879See L<Moose/BUGS> for details on reporting bugs.
c0e30cf5 880
c0e30cf5 881=head1 AUTHOR
882
883Stevan Little E<lt>stevan@iinteractive.comE<gt>
884
885=head1 COPYRIGHT AND LICENSE
886
7e0492d3 887Copyright 2006-2010 by Infinity Interactive, Inc.
c0e30cf5 888
889L<http://www.iinteractive.com>
890
891This library is free software; you can redistribute it and/or modify
ac2dc464 892it under the same terms as Perl itself.
c0e30cf5 893
8a7a9c53 894=cut
1a563243 895