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