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