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