let reinitialization fix metaobjs via role reconciliation
[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
f6df97ae 351sub _find_common_base {
352 my $self = shift;
353 my ($meta1, $meta2) = map { Class::MOP::class_of($_) } @_;
0b91067b 354 return unless defined $meta1 && defined $meta2;
f8b6827f 355
356 # FIXME? This doesn't account for multiple inheritance (not sure
79ca665e 357 # if it needs to though). For example, if somewhere in $meta1's
db9fda52 358 # history it inherits from both ClassA and ClassB, and $meta2
f8b6827f 359 # inherits from ClassB & ClassA, does it matter? And what crazy
360 # fool would do that anyway?
361
362 my %meta1_parents = map { $_ => 1 } $meta1->linearized_isa;
363
364 return first { $meta1_parents{$_} } $meta2->linearized_isa;
365}
366
f6df97ae 367sub _get_ancestors_until {
368 my $self = shift;
dd3ac8f9 369 my ($start_name, $until_name) = @_;
f8b6827f 370
dd3ac8f9 371 my @ancestor_names;
372 for my $ancestor_name (Class::MOP::class_of($start_name)->linearized_isa) {
373 last if $ancestor_name eq $until_name;
374 push @ancestor_names, $ancestor_name;
f6df97ae 375 }
dd3ac8f9 376 return @ancestor_names;
f6df97ae 377}
f8b6827f 378
f6df97ae 379sub _is_role_only_subclass {
380 my $self = shift;
dd3ac8f9 381 my ($meta_name) = @_;
382 my $meta = Class::MOP::Class->initialize($meta_name);
383 my @parent_names = $meta->superclasses;
f6df97ae 384
385 # XXX: don't feel like messing with multiple inheritance here... what would
386 # that even do?
dd3ac8f9 387 return unless @parent_names == 1;
388 my ($parent_name) = @parent_names;
389 my $parent_meta = Class::MOP::Class->initialize($parent_name);
f6df97ae 390
593152a0 391 my @roles = $meta->can('calculate_all_roles_with_inheritance')
392 ? $meta->calculate_all_roles_with_inheritance
393 : ();
394
f6df97ae 395 # loop over all methods that are a part of the current class
396 # (not inherited)
723576c6 397 for my $method ( $meta->_get_local_methods ) {
f6df97ae 398 # always ignore meta
f8b6827f 399 next if $method->name eq 'meta';
f6df97ae 400 # we'll deal with attributes below
593152a0 401 next if $method->can('associated_attribute');
f6df97ae 402 # if the method comes from a role we consumed, ignore it
dd3ac8f9 403 next if $meta->can('does_role')
404 && $meta->does_role($method->original_package_name);
593152a0 405 # FIXME - this really isn't right. Just because a modifier is
406 # defined in a role doesn't mean it isn't _also_ defined in the
407 # subclass.
408 next if $method->isa('Class::MOP::Method::Wrapped')
409 && (
410 (!scalar($method->around_modifiers)
411 || any { $_->has_around_method_modifiers($method->name) } @roles)
412 && (!scalar($method->before_modifiers)
413 || any { $_->has_before_method_modifiers($method->name) } @roles)
414 && (!scalar($method->after_modifiers)
415 || any { $_->has_after_method_modifiers($method->name) } @roles)
416 );
f8b6827f 417
418 return 0;
419 }
420
f6df97ae 421 # loop over all attributes that are a part of the current class
422 # (not inherited)
f8b6827f 423 # FIXME - this really isn't right. Just because an attribute is
424 # defined in a role doesn't mean it isn't _also_ defined in the
425 # subclass.
dd3ac8f9 426 for my $attr (map { $meta->get_attribute($_) } $meta->get_attribute_list) {
593152a0 427 next if any { $_->has_attribute($attr->name) } @roles;
f8b6827f 428
429 return 0;
430 }
431
432 return 1;
433}
434
f6df97ae 435sub _can_fix_class_metaclass_incompatibility_by_role_reconciliation {
436 my $self = shift;
437 my ($super_meta) = @_;
438
a907317a 439 my $super_meta_name = $super_meta->_real_ref_name;
f6df97ae 440
bc9dc5fb 441 return $self->_classes_differ_by_roles_only(
442 blessed($self),
443 $super_meta_name,
444 'Moose::Meta::Class',
445 );
f8b6827f 446}
447
f6df97ae 448sub _can_fix_single_metaclass_incompatibility_by_role_reconciliation {
449 my $self = shift;
dd3ac8f9 450 my ($metaclass_type, $super_meta) = @_;
f8b6827f 451
dd3ac8f9 452 my $class_specific_meta_name = $self->$metaclass_type;
453 return unless $super_meta->can($metaclass_type);
454 my $super_specific_meta_name = $super_meta->$metaclass_type;
f6df97ae 455 my %metaclasses = $self->_base_metaclasses;
f8b6827f 456
bc9dc5fb 457 return $self->_classes_differ_by_roles_only(
458 $class_specific_meta_name,
459 $super_specific_meta_name,
460 $metaclasses{$metaclass_type},
461 );
462}
463
464sub _classes_differ_by_roles_only {
465 my $self = shift;
466 my ( $self_meta_name, $super_meta_name, $expected_ancestor ) = @_;
467
468 my $common_base_name
469 = $self->_find_common_base( $self_meta_name, $super_meta_name );
470
471 # If they're not both moose metaclasses, and the cmop fixing couldn't do
472 # anything, there's nothing more we can do. The $expected_ancestor should
473 # always be a Moose metaclass name like Moose::Meta::Class or
474 # Moose::Meta::Attribute.
0b91067b 475 return unless defined $common_base_name;
bc9dc5fb 476 return unless $common_base_name->isa($expected_ancestor);
477
478 my @super_meta_name_ancestor_names
479 = $self->_get_ancestors_until( $super_meta_name, $common_base_name );
480 my @class_meta_name_ancestor_names
481 = $self->_get_ancestors_until( $self_meta_name, $common_base_name );
482
483 return
484 unless all { $self->_is_role_only_subclass($_) }
485 @super_meta_name_ancestor_names,
486 @class_meta_name_ancestor_names;
f8b6827f 487
f6df97ae 488 return 1;
489}
f8b6827f 490
f6df97ae 491sub _role_differences {
492 my $self = shift;
dd3ac8f9 493 my ($class_meta_name, $super_meta_name) = @_;
9f83eb5d 494 my @super_role_metas = $super_meta_name->meta->can('calculate_all_roles_with_inheritance')
495 ? $super_meta_name->meta->calculate_all_roles_with_inheritance
dd3ac8f9 496 : ();
9f83eb5d 497 my @role_metas = $class_meta_name->meta->can('calculate_all_roles_with_inheritance')
498 ? $class_meta_name->meta->calculate_all_roles_with_inheritance
dd3ac8f9 499 : ();
f6df97ae 500 my @differences;
dd3ac8f9 501 for my $role_meta (@role_metas) {
502 push @differences, $role_meta
503 unless any { $_->name eq $role_meta->name } @super_role_metas;
f8b6827f 504 }
f6df97ae 505 return @differences;
f8b6827f 506}
507
f6df97ae 508sub _reconcile_roles_for_metaclass {
509 my $self = shift;
dd3ac8f9 510 my ($class_meta_name, $super_meta_name) = @_;
f8b6827f 511
dd3ac8f9 512 my @role_differences = $self->_role_differences(
513 $class_meta_name, $super_meta_name,
514 );
b85607ab 515
516 # handle the case where we need to fix compatibility between a class and
517 # its parent, but all roles in the class are already also done by the
518 # parent
519 # see t/050/054.t
520 return Class::MOP::class_of($super_meta_name)
521 unless @role_differences;
522
9f83eb5d 523 return Moose::Meta::Class->create_anon_class(
dd3ac8f9 524 superclasses => [$super_meta_name],
ebff3004 525 roles => [map { $_->name } @role_differences],
f6df97ae 526 cache => 1,
527 );
528}
529
530sub _can_fix_metaclass_incompatibility_by_role_reconciliation {
531 my $self = shift;
532 my ($super_meta) = @_;
f8b6827f 533
f6df97ae 534 return 1 if $self->_can_fix_class_metaclass_incompatibility_by_role_reconciliation($super_meta);
f8b6827f 535
f6df97ae 536 my %base_metaclass = $self->_base_metaclasses;
537 for my $metaclass_type (keys %base_metaclass) {
538 next unless defined $self->$metaclass_type;
539 return 1 if $self->_can_fix_single_metaclass_incompatibility_by_role_reconciliation($metaclass_type, $super_meta);
f8b6827f 540 }
541
f6df97ae 542 return;
543}
f8b6827f 544
f6df97ae 545sub _can_fix_metaclass_incompatibility {
546 my $self = shift;
547 return 1 if $self->_can_fix_metaclass_incompatibility_by_role_reconciliation(@_);
548 return $self->SUPER::_can_fix_metaclass_incompatibility(@_);
549}
550
551sub _fix_class_metaclass_incompatibility {
552 my $self = shift;
553 my ($super_meta) = @_;
f8b6827f 554
f6df97ae 555 $self->SUPER::_fix_class_metaclass_incompatibility(@_);
f8b6827f 556
f6df97ae 557 if ($self->_can_fix_class_metaclass_incompatibility_by_role_reconciliation($super_meta)) {
590e8894 558 ($self->is_pristine)
559 || confess "Can't fix metaclass incompatibility for "
560 . $self->name
561 . " because it is not pristine.";
a907317a 562 my $super_meta_name = $super_meta->_real_ref_name;
9f83eb5d 563 my $class_meta_subclass_meta = $self->_reconcile_roles_for_metaclass(blessed($self), $super_meta_name);
cf7febc7 564 my $new_self = $class_meta_subclass_meta->name->reinitialize(
565 $self->name,
566 );
6a52b083 567
568 $self->_replace_self( $new_self, $class_meta_subclass_meta->name );
f8b6827f 569 }
f6df97ae 570}
f8b6827f 571
f6df97ae 572sub _fix_single_metaclass_incompatibility {
573 my $self = shift;
574 my ($metaclass_type, $super_meta) = @_;
f8b6827f 575
f6df97ae 576 $self->SUPER::_fix_single_metaclass_incompatibility(@_);
f8b6827f 577
f6df97ae 578 if ($self->_can_fix_single_metaclass_incompatibility_by_role_reconciliation($metaclass_type, $super_meta)) {
590e8894 579 ($self->is_pristine)
580 || confess "Can't fix metaclass incompatibility for "
581 . $self->name
582 . " because it is not pristine.";
7f6c8567 583 my $super_meta_name = $super_meta->_real_ref_name;
dd3ac8f9 584 my $class_specific_meta_subclass_meta = $self->_reconcile_roles_for_metaclass($self->$metaclass_type, $super_meta->$metaclass_type);
cf7febc7 585 my $new_self = $super_meta->reinitialize(
586 $self->name,
587 $metaclass_type => $class_specific_meta_subclass_meta->name,
588 );
6a52b083 589
7f6c8567 590 $self->_replace_self( $new_self, $super_meta_name );
f6df97ae 591 }
f8b6827f 592}
593
6a52b083 594
595sub _replace_self {
596 my $self = shift;
597 my ( $new_self, $new_class) = @_;
598
599 %$self = %$new_self;
600 bless $self, $new_class;
601
602 # We need to replace the cached metaclass instance or else when it goes
603 # out of scope Class::MOP::Class destroy's the namespace for the
604 # metaclass's class, causing much havoc.
605 Class::MOP::store_metaclass_by_name( $self->name, $self );
606 Class::MOP::weaken_metaclass( $self->name ) if $self->is_anon_class;
607}
608
c1f0275a 609sub _get_compatible_single_metaclass_by_role_reconciliation {
610 my $self = shift;
611 my ($single_meta_name) = @_;
612
613 my $current_single_meta_name = $self->_get_associated_single_metaclass($single_meta_name);
614
615 return $self->_reconcile_roles_for_metaclass($single_meta_name, $current_single_meta_name)->name;
616}
617
618sub _get_compatible_single_metaclass {
619 my $self = shift;
620
621 return $self->SUPER::_get_compatible_single_metaclass(@_)
622 || $self->_get_compatible_single_metaclass_by_role_reconciliation(@_);
623}
624
1341f10c 625sub _process_attribute {
a3738e5b 626 my ( $self, $name, @args ) = @_;
7e59b803 627
628 @args = %{$args[0]} if scalar @args == 1 && ref($args[0]) eq 'HASH';
d9bb6c63 629
f9b5f5f8 630 if (($name || '') =~ /^\+(.*)/) {
7e59b803 631 return $self->_process_inherited_attribute($1, @args);
1341f10c 632 }
633 else {
7e59b803 634 return $self->_process_new_attribute($name, @args);
635 }
636}
637
638sub _process_new_attribute {
639 my ( $self, $name, @args ) = @_;
7e59b803 640
d5c30e52 641 $self->attribute_metaclass->interpolate_class_and_new($name, @args);
1341f10c 642}
643
644sub _process_inherited_attribute {
645 my ($self, $attr_name, %options) = @_;
646 my $inherited_attr = $self->find_attribute_by_name($attr_name);
647 (defined $inherited_attr)
329c5dd4 648 || $self->throw_error("Could not find an attribute by the name of '$attr_name' to inherit from in ${\$self->name}", data => $attr_name);
1341f10c 649 if ($inherited_attr->isa('Moose::Meta::Attribute')) {
d7d8a8c7 650 return $inherited_attr->clone_and_inherit_options(%options);
1341f10c 651 }
652 else {
653 # NOTE:
654 # kind of a kludge to handle Class::MOP::Attributes
d7d8a8c7 655 return $inherited_attr->Moose::Meta::Attribute::clone_and_inherit_options(%options);
ac2dc464 656 }
1341f10c 657}
658
948cd189 659## Immutability
660
661sub _immutable_options {
662 my ( $self, @args ) = @_;
663
664 $self->SUPER::_immutable_options(
665 inline_destructor => 1,
948cd189 666
667 # Moose always does this when an attribute is created
668 inline_accessors => 0,
669
670 @args,
671 );
672}
673
5cf3dbcf 674## -------------------------------------------------
675
bf6fa6b3 676our $error_level;
11c86f15 677
678sub throw_error {
679 my ( $self, @args ) = @_;
bf6fa6b3 680 local $error_level = ($error_level || 0) + 1;
11c86f15 681 $self->raise_error($self->create_error(@args));
682}
683
684sub raise_error {
685 my ( $self, @args ) = @_;
686 die @args;
687}
688
689sub create_error {
690 my ( $self, @args ) = @_;
691
18748ad6 692 require Carp::Heavy;
693
bf6fa6b3 694 local $error_level = ($error_level || 0 ) + 1;
18748ad6 695
11c86f15 696 if ( @args % 2 == 1 ) {
697 unshift @args, "message";
698 }
699
fcab1742 700 my %args = ( metaclass => $self, last_error => $@, @args );
11c86f15 701
bf6fa6b3 702 $args{depth} += $error_level;
11c86f15 703
bf6fa6b3 704 my $class = ref $self ? $self->error_class : "Moose::Error::Default";
11c86f15 705
a810a01f 706 Class::MOP::load_class($class);
707
11c86f15 708 $class->new(
bf6fa6b3 709 Carp::caller_info($args{depth}),
710 %args
11c86f15 711 );
712}
713
c0e30cf5 7141;
715
716__END__
717
718=pod
719
720=head1 NAME
721
e522431d 722Moose::Meta::Class - The Moose metaclass
c0e30cf5 723
c0e30cf5 724=head1 DESCRIPTION
725
70bb0f97 726This class is a subclass of L<Class::MOP::Class> that provides
727additional Moose-specific functionality.
e522431d 728
7854b409 729To really understand this class, you will need to start with the
730L<Class::MOP::Class> documentation. This class can be understood as a
731set of additional features on top of the basic feature provided by
732that parent class.
6ba6d68c 733
d4b1449e 734=head1 INHERITANCE
735
736C<Moose::Meta::Class> is a subclass of L<Class::MOP::Class>.
737
c0e30cf5 738=head1 METHODS
739
740=over 4
741
70bb0f97 742=item B<< Moose::Meta::Class->initialize($package_name, %options) >>
590868a3 743
70bb0f97 744This overrides the parent's method in order to provide its own
745defaults for the C<attribute_metaclass>, C<instance_metaclass>, and
746C<method_metaclass> options.
61bdd94f 747
70bb0f97 748These all default to the appropriate Moose class.
61bdd94f 749
70bb0f97 750=item B<< Moose::Meta::Class->create($package_name, %options) >>
17594769 751
70bb0f97 752This overrides the parent's method in order to accept a C<roles>
9e25a72a 753option. This should be an array reference containing roles
754that the class does, each optionally followed by a hashref of options
755(C<-excludes> and C<-alias>).
17594769 756
70bb0f97 757 my $metaclass = Moose::Meta::Class->create( 'New::Class', roles => [...] );
17594769 758
70bb0f97 759=item B<< Moose::Meta::Class->create_anon_class >>
17594769 760
70bb0f97 761This overrides the parent's method to accept a C<roles> option, just
762as C<create> does.
5cf3dbcf 763
70bb0f97 764It also accepts a C<cache> option. If this is true, then the anonymous
765class will be cached based on its superclasses and roles. If an
766existing anonymous class in the cache has the same superclasses and
767roles, it will be reused.
ac2dc464 768
70bb0f97 769 my $metaclass = Moose::Meta::Class->create_anon_class(
770 superclasses => ['Foo'],
771 roles => [qw/Some Roles Go Here/],
772 cache => 1,
773 );
ac2dc464 774
2e7f6cf4 775Each entry in both the C<superclasses> and the C<roles> option can be
b2d54db8 776followed by a hash reference with arguments. The C<superclasses>
2e7f6cf4 777option can be supplied with a L<-version|Class::MOP/Class Loading
778Options> option that ensures the loaded superclass satisfies the
779required version. The C<role> option also takes the C<-version> as an
780argument, but the option hash reference can also contain any other
781role relevant values like exclusions or parameterized role arguments.
782
70bb0f97 783=item B<< $metaclass->make_immutable(%options) >>
ac2dc464 784
70bb0f97 785This overrides the parent's method to add a few options. Specifically,
786it uses the Moose-specific constructor and destructor classes, and
787enables inlining the destructor.
8c9d74e7 788
dcdceb38 789Since Moose always inlines attributes, it sets the C<inline_accessors> option
790to false.
791
70bb0f97 792=item B<< $metaclass->new_object(%params) >>
a15dff8d 793
70bb0f97 794This overrides the parent's method in order to add support for
795attribute triggers.
6ba6d68c 796
2e7f6cf4 797=item B<< $metaclass->superclasses(@superclasses) >>
798
6b958a3e 799This is the accessor allowing you to read or change the parents of
2e7f6cf4 800the class.
801
802Each superclass can be followed by a hash reference containing a
803L<-version|Class::MOP/Class Loading Options> value. If the version
804requirement is not satisfied an error will be thrown.
805
70bb0f97 806=item B<< $metaclass->add_override_method_modifier($name, $sub) >>
ef1d5f4b 807
70bb0f97 808This adds an C<override> method modifier to the package.
e9ec68d6 809
70bb0f97 810=item B<< $metaclass->add_augment_method_modifier($name, $sub) >>
e9ec68d6 811
70bb0f97 812This adds an C<augment> method modifier to the package.
78cd1d3b 813
70bb0f97 814=item B<< $metaclass->calculate_all_roles >>
02a0fb52 815
70bb0f97 816This will return a unique array of C<Moose::Meta::Role> instances
817which are attached to this class.
78cd1d3b 818
9f83eb5d 819=item B<< $metaclass->calculate_all_roles_with_inheritance >>
820
821This will return a unique array of C<Moose::Meta::Role> instances
822which are attached to this class, and each of this class's ancestors.
823
70bb0f97 824=item B<< $metaclass->add_role($role) >>
02a0fb52 825
70bb0f97 826This takes a L<Moose::Meta::Role> object, and adds it to the class's
827list of roles. This I<does not> actually apply the role to the class.
2b14ac61 828
b90dd4ef 829=item B<< $metaclass->role_applications >>
830
639f9a1a 831Returns a list of L<Moose::Meta::Role::Application::ToClass>
b90dd4ef 832objects, which contain the arguments to role application.
833
834=item B<< $metaclass->add_role_application($application) >>
835
836This takes a L<Moose::Meta::Role::Application::ToClass> object, and
837adds it to the class's list of role applications. This I<does not>
838actually apply any role to the class; it is only for tracking role
839applications.
840
560c498d 841=item B<< $metaclass->does_role($role) >>
ef333f17 842
560c498d 843This returns a boolean indicating whether or not the class does the specified
844role. The role provided can be either a role name or a L<Moose::Meta::Role>
845object. This tests both the class and its parents.
02a0fb52 846
70bb0f97 847=item B<< $metaclass->excludes_role($role_name) >>
ef333f17 848
70bb0f97 849A class excludes a role if it has already composed a role which
850excludes the named role. This tests both the class and its parents.
02a0fb52 851
70bb0f97 852=item B<< $metaclass->add_attribute($attr_name, %params|$params) >>
ef333f17 853
70bb0f97 854This overrides the parent's method in order to allow the parameters to
855be provided as a hash reference.
02a0fb52 856
9f9fdd08 857=item B<< $metaclass->constructor_class($class_name) >>
d79e62fd 858
9f9fdd08 859=item B<< $metaclass->destructor_class($class_name) >>
e606ae5f 860
948cd189 861These are the names of classes used when making a class immutable. These
90a49845 862default to L<Moose::Meta::Method::Constructor> and
863L<Moose::Meta::Method::Destructor> respectively. These accessors are
864read-write, so you can use them to change the class name.
e606ae5f 865
70bb0f97 866=item B<< $metaclass->error_class($class_name) >>
8b1d510f 867
70bb0f97 868The name of the class used to throw errors. This defaults to
8b1d510f 869L<Moose::Error::Default>, which generates an error with a stacktrace
870just like C<Carp::confess>.
871
70bb0f97 872=item B<< $metaclass->throw_error($message, %extra) >>
11c86f15 873
874Throws the error created by C<create_error> using C<raise_error>
875
c0e30cf5 876=back
877
878=head1 BUGS
879
d4048ef3 880See L<Moose/BUGS> for details on reporting bugs.
c0e30cf5 881
c0e30cf5 882=head1 AUTHOR
883
884Stevan Little E<lt>stevan@iinteractive.comE<gt>
885
886=head1 COPYRIGHT AND LICENSE
887
7e0492d3 888Copyright 2006-2010 by Infinity Interactive, Inc.
c0e30cf5 889
890L<http://www.iinteractive.com>
891
892This library is free software; you can redistribute it and/or modify
ac2dc464 893it under the same terms as Perl itself.
c0e30cf5 894
8a7a9c53 895=cut
1a563243 896