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