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