some style tweaks to t0m's change to the metaclass compat fixing code.
[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
11c86f15 9use Carp ();
f8b6827f 10use List::Util qw( first );
349cda54 11use List::MoreUtils qw( any all uniq first_index );
21f1e231 12use Scalar::Util 'weaken', 'blessed';
a15dff8d 13
75d2da34 14our $VERSION = '0.77';
e606ae5f 15$VERSION = eval $VERSION;
d44714be 16our $AUTHORITY = 'cpan:STEVAN';
bc1e29b5 17
74862722 18use Moose::Meta::Method::Overridden;
3f9e4b0a 19use Moose::Meta::Method::Augmented;
bf6fa6b3 20use Moose::Error::Default;
0fa70d03 21use Moose::Meta::Class::Immutable::Trait;
22use Moose::Meta::Method::Constructor;
23use Moose::Meta::Method::Destructor;
8ee73eeb 24
c0e30cf5 25use base 'Class::MOP::Class';
26
598340d5 27__PACKAGE__->meta->add_attribute('roles' => (
ef333f17 28 reader => 'roles',
29 default => sub { [] }
30));
31
a9b63d79 32__PACKAGE__->meta->add_attribute('role_applications' => (
639f9a1a 33 reader => '_get_role_applications',
a9b63d79 34 default => sub { [] }
35));
36
0fa70d03 37__PACKAGE__->meta->add_attribute(
38 Class::MOP::Attribute->new('immutable_trait' => (
39 accessor => "immutable_trait",
40 default => 'Moose::Meta::Class::Immutable::Trait',
41 ))
42);
43
e606ae5f 44__PACKAGE__->meta->add_attribute('constructor_class' => (
45 accessor => 'constructor_class',
e0001338 46 default => 'Moose::Meta::Method::Constructor',
e606ae5f 47));
48
49__PACKAGE__->meta->add_attribute('destructor_class' => (
50 accessor => 'destructor_class',
e0001338 51 default => 'Moose::Meta::Method::Destructor',
e606ae5f 52));
53
11c86f15 54__PACKAGE__->meta->add_attribute('error_class' => (
bf6fa6b3 55 accessor => 'error_class',
56 default => 'Moose::Error::Default',
11c86f15 57));
58
590868a3 59sub initialize {
60 my $class = shift;
61 my $pkg = shift;
d03bd989 62 return Class::MOP::get_metaclass_by_name($pkg)
685f7e44 63 || $class->SUPER::initialize($pkg,
64 'attribute_metaclass' => 'Moose::Meta::Attribute',
65 'method_metaclass' => 'Moose::Meta::Method',
66 'instance_metaclass' => 'Moose::Meta::Instance',
67 @_
d03bd989 68 );
ac2dc464 69}
590868a3 70
0fa70d03 71sub _immutable_options {
72 my ( $self, @args ) = @_;
73
74 $self->SUPER::_immutable_options(
75 inline_destructor => 1,
76
77 # Moose always does this when an attribute is created
78 inline_accessors => 0,
79
80 @args,
81 );
82}
83
61bdd94f 84sub create {
85 my ($self, $package_name, %options) = @_;
d03bd989 86
61bdd94f 87 (ref $options{roles} eq 'ARRAY')
11c86f15 88 || $self->throw_error("You must pass an ARRAY ref of roles", data => $options{roles})
61bdd94f 89 if exists $options{roles};
310ba883 90 my $roles = delete $options{roles};
dd37a5be 91
61bdd94f 92 my $class = $self->SUPER::create($package_name, %options);
dd37a5be 93
310ba883 94 if ($roles) {
95 Moose::Util::apply_all_roles( $class, @$roles );
61bdd94f 96 }
d03bd989 97
61bdd94f 98 return $class;
99}
100
6a4a7c31 101sub _check_metaclass_compatibility {
2b72f3b4 102 my $self = shift;
103
104 if ( my @supers = $self->superclasses ) {
105 $self->_fix_metaclass_incompatibility(@supers);
106 }
107
6a4a7c31 108 $self->SUPER::_check_metaclass_compatibility(@_);
2b72f3b4 109}
110
17594769 111my %ANON_CLASSES;
112
113sub create_anon_class {
114 my ($self, %options) = @_;
115
116 my $cache_ok = delete $options{cache};
d03bd989 117
17594769 118 # something like Super::Class|Super::Class::2=Role|Role::1
119 my $cache_key = join '=' => (
11aaed6c 120 join('|', @{$options{superclasses} || []}),
121 join('|', sort @{$options{roles} || []}),
17594769 122 );
d03bd989 123
6d5cbd2b 124 if ($cache_ok && defined $ANON_CLASSES{$cache_key}) {
17594769 125 return $ANON_CLASSES{$cache_key};
126 }
d03bd989 127
17594769 128 my $new_class = $self->SUPER::create_anon_class(%options);
129
6d5cbd2b 130 $ANON_CLASSES{$cache_key} = $new_class
131 if $cache_ok;
17594769 132
133 return $new_class;
134}
135
ef333f17 136sub add_role {
137 my ($self, $role) = @_;
138 (blessed($role) && $role->isa('Moose::Meta::Role'))
11c86f15 139 || $self->throw_error("Roles must be instances of Moose::Meta::Role", data => $role);
ef333f17 140 push @{$self->roles} => $role;
141}
142
639f9a1a 143sub role_applications {
144 my ($self) = @_;
145
146 return @{$self->_get_role_applications};
147}
148
a9b63d79 149sub add_role_application {
150 my ($self, $application) = @_;
151 (blessed($application) && $application->isa('Moose::Meta::Role::Application::ToClass'))
152 || $self->throw_error("Role applications must be instances of Moose::Meta::Role::Application::ToClass", data => $application);
639f9a1a 153 push @{$self->_get_role_applications} => $application;
a9b63d79 154}
155
b8aeb4dc 156sub calculate_all_roles {
157 my $self = shift;
158 my %seen;
159 grep { !$seen{$_->name}++ } map { $_->calculate_all_roles } @{ $self->roles };
160}
161
ef333f17 162sub does_role {
163 my ($self, $role_name) = @_;
322abb07 164
ef333f17 165 (defined $role_name)
11c86f15 166 || $self->throw_error("You must supply a role name to look for");
322abb07 167
9c429218 168 foreach my $class ($self->class_precedence_list) {
322abb07 169 my $meta = Class::MOP::class_of($class);
3d0f5a27 170 # when a Moose metaclass is itself extended with a role,
171 # this check needs to be done since some items in the
172 # class_precedence_list might in fact be Class::MOP
173 # based still.
322abb07 174 next unless $meta && $meta->can('roles');
175 foreach my $role (@{$meta->roles}) {
9c429218 176 return 1 if $role->does_role($role_name);
177 }
ef333f17 178 }
179 return 0;
180}
181
d79e62fd 182sub excludes_role {
183 my ($self, $role_name) = @_;
ebfc4d0f 184
d79e62fd 185 (defined $role_name)
11c86f15 186 || $self->throw_error("You must supply a role name to look for");
ebfc4d0f 187
ac2dc464 188 foreach my $class ($self->class_precedence_list) {
ebfc4d0f 189 my $meta = Class::MOP::class_of($class);
190 # when a Moose metaclass is itself extended with a role,
191 # this check needs to be done since some items in the
192 # class_precedence_list might in fact be Class::MOP
193 # based still.
194 next unless $meta && $meta->can('roles');
195 foreach my $role (@{$meta->roles}) {
9c429218 196 return 1 if $role->excludes_role($role_name);
197 }
d79e62fd 198 }
199 return 0;
200}
201
8c9d74e7 202sub new_object {
1308deb4 203 my $class = shift;
e606ae5f 204 my $params = @_ == 1 ? $_[0] : {@_};
1308deb4 205 my $self = $class->SUPER::new_object($params);
206
b2df9268 207 foreach my $attr ( $class->get_all_attributes() ) {
1308deb4 208
209 next unless $attr->can('has_trigger') && $attr->has_trigger;
210
211 my $init_arg = $attr->init_arg;
212
213 next unless defined $init_arg;
214
215 next unless exists $params->{$init_arg};
216
217 $attr->trigger->(
218 $self,
219 (
220 $attr->should_coerce
221 ? $attr->get_read_method_ref->($self)
222 : $params->{$init_arg}
223 ),
1308deb4 224 );
8c9d74e7 225 }
1308deb4 226
ac2dc464 227 return $self;
8c9d74e7 228}
229
b2df9268 230sub _construct_instance {
e606ae5f 231 my $class = shift;
232 my $params = @_ == 1 ? $_[0] : {@_};
ddd0ec20 233 my $meta_instance = $class->get_meta_instance;
575db57d 234 # FIXME:
235 # the code below is almost certainly incorrect
6549b0d1 236 # but this is foreign inheritance, so we might
ac2dc464 237 # have to kludge it in the end.
e606ae5f 238 my $instance = $params->{'__INSTANCE__'} || $meta_instance->create_instance();
b2df9268 239 foreach my $attr ($class->get_all_attributes()) {
e606ae5f 240 $attr->initialize_instance_slot($meta_instance, $instance, $params);
a15dff8d 241 }
242 return $instance;
243}
244
e2eef3a5 245sub superclasses {
246 my $self = shift;
247 my @supers = @_;
248 foreach my $super (@supers) {
249 my $meta = Class::MOP::load_class($super);
250 Moose->throw_error("You cannot inherit from a Moose Role ($super)")
251 if $meta && $meta->isa('Moose::Meta::Role')
252 }
253 return $self->SUPER::superclasses(@supers);
254}
255
093b12c2 256### ---------------------------------------------
257
a2eec5e7 258sub add_attribute {
259 my $self = shift;
e472c9a5 260 $self->SUPER::add_attribute(
261 (blessed $_[0] && $_[0]->isa('Class::MOP::Attribute')
d03bd989 262 ? $_[0]
263 : $self->_process_attribute(@_))
e472c9a5 264 );
a2eec5e7 265}
266
78cd1d3b 267sub add_override_method_modifier {
268 my ($self, $name, $method, $_super_package) = @_;
18c2ec0e 269
d05cd563 270 (!$self->has_method($name))
11c86f15 271 || $self->throw_error("Cannot add an override method if a local method is already present");
18c2ec0e 272
74862722 273 $self->add_method($name => Moose::Meta::Method::Overridden->new(
3f9e4b0a 274 method => $method,
275 class => $self,
276 package => $_super_package, # need this for roles
277 name => $name,
18c2ec0e 278 ));
78cd1d3b 279}
280
281sub add_augment_method_modifier {
ac2dc464 282 my ($self, $name, $method) = @_;
d05cd563 283 (!$self->has_method($name))
11c86f15 284 || $self->throw_error("Cannot add an augment method if a local method is already present");
3f9e4b0a 285
286 $self->add_method($name => Moose::Meta::Method::Augmented->new(
287 method => $method,
288 class => $self,
289 name => $name,
290 ));
78cd1d3b 291}
292
1341f10c 293## Private Utility methods ...
294
05d9eaf6 295sub _find_next_method_by_name_which_is_not_overridden {
296 my ($self, $name) = @_;
68efb014 297 foreach my $method ($self->find_all_methods_by_name($name)) {
ac2dc464 298 return $method->{code}
74862722 299 if blessed($method->{code}) && !$method->{code}->isa('Moose::Meta::Method::Overridden');
05d9eaf6 300 }
301 return undef;
302}
303
41419b9e 304sub _fix_metaclass_incompatibility {
1341f10c 305 my ($self, @superclasses) = @_;
e606ae5f 306
1341f10c 307 foreach my $super (@superclasses) {
349cda54 308 my $meta = Class::MOP::Class->initialize($super);
309
310 my @all_supers = $meta->linearized_isa;
cb311121 311 shift @all_supers;
312
313 my @super_metas_to_fix = ($meta);
314
315 # We need to check & fix the immediate superclass. If its @ISA
316 # contains a class without a metaclass instance, followed by a
317 # class _with_ a metaclass instance, init a metaclass instance
318 # for classes without one and fix compat up to and including
319 # the class which was already initialized.
349cda54 320 my $idx = first_index { Class::MOP::class_of($_) } @all_supers;
cb311121 321
322 push @super_metas_to_fix,
323 map { Class::MOP::Class->initialize($_) } @all_supers[ 0 .. $idx ]
324 if $idx >= 0;
349cda54 325
326 foreach my $super_meta (@super_metas_to_fix) {
327 $self->_fix_one_incompatible_metaclass($super_meta);
1341f10c 328 }
349cda54 329 }
330}
331
332sub _fix_one_incompatible_metaclass {
333 my ($self, $meta) = @_;
e606ae5f 334
349cda54 335 return if $self->_superclass_meta_is_compatible($meta);
336
337 unless ( $self->is_pristine ) {
338 $self->throw_error(
339 "Cannot attempt to reinitialize metaclass for "
340 . $self->name
341 . ", it isn't pristine" );
f8b6827f 342 }
cb311121 343
349cda54 344 $self->_reconcile_with_superclass_meta($meta);
f8b6827f 345}
346
347sub _superclass_meta_is_compatible {
349cda54 348 my ($self, $super_meta) = @_;
f8b6827f 349
350 next unless $super_meta->isa("Class::MOP::Class");
351
352 my $super_meta_name
353 = $super_meta->is_immutable
354 ? $super_meta->get_mutable_metaclass_name
355 : ref($super_meta);
356
357 return 1
358 if $self->isa($super_meta_name)
359 and
360 $self->instance_metaclass->isa( $super_meta->instance_metaclass );
361}
362
363# I don't want to have to type this >1 time
364my @MetaClassTypes =
3e334262 365 qw( attribute_metaclass
366 method_metaclass
367 wrapped_method_metaclass
368 instance_metaclass
369 constructor_class
370 destructor_class
371 error_class );
f8b6827f 372
373sub _reconcile_with_superclass_meta {
349cda54 374 my ($self, $super_meta) = @_;
f8b6827f 375
dd37a5be 376 my $super_meta_name
f8b6827f 377 = $super_meta->is_immutable
378 ? $super_meta->get_mutable_metaclass_name
379 : ref($super_meta);
e606ae5f 380
f8b6827f 381 my $self_metaclass = ref $self;
382
383 # If neither of these is true we have a more serious
384 # incompatibility that we just cannot fix (yet?).
dd37a5be 385 if ( $super_meta_name->isa( ref $self )
f8b6827f 386 && all { $super_meta->$_->isa( $self->$_ ) } @MetaClassTypes ) {
0635500e 387 $self->_reinitialize_with($super_meta);
f8b6827f 388 }
389 elsif ( $self->_all_metaclasses_differ_by_roles_only($super_meta) ) {
0635500e 390 $self->_reconcile_role_differences($super_meta);
1341f10c 391 }
1341f10c 392}
393
f8b6827f 394sub _reinitialize_with {
395 my ( $self, $new_meta ) = @_;
396
0635500e 397 my $new_self = $new_meta->reinitialize(
f8b6827f 398 $self->name,
399 attribute_metaclass => $new_meta->attribute_metaclass,
400 method_metaclass => $new_meta->method_metaclass,
401 instance_metaclass => $new_meta->instance_metaclass,
402 );
403
8b1d510f 404 $new_self->$_( $new_meta->$_ )
405 for qw( constructor_class destructor_class error_class );
f8b6827f 406
0635500e 407 %$self = %$new_self;
408
409 bless $self, ref $new_self;
410
4c5fcc12 411 # We need to replace the cached metaclass instance or else when it
412 # goes out of scope Class::MOP::Class destroy's the namespace for
413 # the metaclass's class, causing much havoc.
0635500e 414 Class::MOP::store_metaclass_by_name( $self->name, $self );
4c5fcc12 415 Class::MOP::weaken_metaclass( $self->name ) if $self->is_anon_class;
f8b6827f 416}
417
418# In the more complex case, we share a common ancestor with our
419# superclass's metaclass, but each metaclass (ours and the parent's)
420# has a different set of roles applied. We reconcile this by first
421# reinitializing into the parent class, and _then_ applying our own
422# roles.
423sub _all_metaclasses_differ_by_roles_only {
424 my ($self, $super_meta) = @_;
425
426 for my $pair (
427 [ ref $self, ref $super_meta ],
428 map { [ $self->$_, $super_meta->$_ ] } @MetaClassTypes
429 ) {
430
431 next if $pair->[0] eq $pair->[1];
432
433 my $self_meta_meta = Class::MOP::Class->initialize( $pair->[0] );
434 my $super_meta_meta = Class::MOP::Class->initialize( $pair->[1] );
435
436 my $common_ancestor
437 = _find_common_ancestor( $self_meta_meta, $super_meta_meta );
438
439 return unless $common_ancestor;
440
441 return
442 unless _is_role_only_subclass_of(
443 $self_meta_meta,
444 $common_ancestor,
445 )
446 && _is_role_only_subclass_of(
447 $super_meta_meta,
448 $common_ancestor,
449 );
450 }
451
452 return 1;
453}
454
455# This, and some other functions, could be called as methods, but
456# they're not for two reasons. One, we just end up ignoring the first
457# argument, because we can't call these directly on one of the real
458# arguments, because one of them could be a Class::MOP::Class object
459# and not a Moose::Meta::Class. Second, only a completely insane
460# person would attempt to subclass this stuff!
461sub _find_common_ancestor {
462 my ($meta1, $meta2) = @_;
463
464 # FIXME? This doesn't account for multiple inheritance (not sure
465 # if it needs to though). For example, is somewhere in $meta1's
db9fda52 466 # history it inherits from both ClassA and ClassB, and $meta2
f8b6827f 467 # inherits from ClassB & ClassA, does it matter? And what crazy
468 # fool would do that anyway?
469
470 my %meta1_parents = map { $_ => 1 } $meta1->linearized_isa;
471
472 return first { $meta1_parents{$_} } $meta2->linearized_isa;
473}
474
475sub _is_role_only_subclass_of {
476 my ($meta, $ancestor) = @_;
477
478 return 1 if $meta->name eq $ancestor;
479
480 my @roles = _all_roles_until( $meta, $ancestor );
481
482 my %role_packages = map { $_->name => 1 } @roles;
483
484 my $ancestor_meta = Class::MOP::Class->initialize($ancestor);
485
486 my %shared_ancestors = map { $_ => 1 } $ancestor_meta->linearized_isa;
487
488 for my $method ( $meta->get_all_methods() ) {
489 next if $method->name eq 'meta';
490 next if $method->can('associated_attribute');
491
492 next
493 if $role_packages{ $method->original_package_name }
494 || $shared_ancestors{ $method->original_package_name };
495
496 return 0;
497 }
498
499 # FIXME - this really isn't right. Just because an attribute is
500 # defined in a role doesn't mean it isn't _also_ defined in the
501 # subclass.
502 for my $attr ( $meta->get_all_attributes ) {
503 next if $shared_ancestors{ $attr->associated_class->name };
504
505 next if any { $_->has_attribute( $attr->name ) } @roles;
506
507 return 0;
508 }
509
510 return 1;
511}
512
513sub _all_roles {
514 my $meta = shift;
515
516 return _all_roles_until($meta);
517}
518
519sub _all_roles_until {
520 my ($meta, $stop_at_class) = @_;
521
522 return unless $meta->can('calculate_all_roles');
523
524 my @roles = $meta->calculate_all_roles;
525
526 for my $class ( $meta->linearized_isa ) {
527 last if $stop_at_class && $stop_at_class eq $class;
528
529 my $meta = Class::MOP::Class->initialize($class);
530 last unless $meta->can('calculate_all_roles');
531
532 push @roles, $meta->calculate_all_roles;
533 }
534
8b1d510f 535 return uniq @roles;
f8b6827f 536}
537
538sub _reconcile_role_differences {
539 my ($self, $super_meta) = @_;
540
3897e146 541 my $self_meta = Class::MOP::class_of($self);
f8b6827f 542
543 my %roles;
544
545 if ( my @roles = map { $_->name } _all_roles($self_meta) ) {
546 $roles{metaclass_roles} = \@roles;
547 }
548
549 for my $thing (@MetaClassTypes) {
550 my $name = $self->$thing();
551
552 my $thing_meta = Class::MOP::Class->initialize($name);
553
554 my @roles = map { $_->name } _all_roles($thing_meta)
555 or next;
556
557 $roles{ $thing . '_roles' } = \@roles;
558 }
559
2b72f3b4 560 $self->_reinitialize_with($super_meta);
f8b6827f 561
562 Moose::Util::MetaRole::apply_metaclass_roles(
563 for_class => $self->name,
564 %roles,
565 );
566
567 return $self;
568}
569
1341f10c 570sub _process_attribute {
a3738e5b 571 my ( $self, $name, @args ) = @_;
7e59b803 572
573 @args = %{$args[0]} if scalar @args == 1 && ref($args[0]) eq 'HASH';
d9bb6c63 574
f9b5f5f8 575 if (($name || '') =~ /^\+(.*)/) {
7e59b803 576 return $self->_process_inherited_attribute($1, @args);
1341f10c 577 }
578 else {
7e59b803 579 return $self->_process_new_attribute($name, @args);
580 }
581}
582
583sub _process_new_attribute {
584 my ( $self, $name, @args ) = @_;
7e59b803 585
d5c30e52 586 $self->attribute_metaclass->interpolate_class_and_new($name, @args);
1341f10c 587}
588
589sub _process_inherited_attribute {
590 my ($self, $attr_name, %options) = @_;
591 my $inherited_attr = $self->find_attribute_by_name($attr_name);
592 (defined $inherited_attr)
329c5dd4 593 || $self->throw_error("Could not find an attribute by the name of '$attr_name' to inherit from in ${\$self->name}", data => $attr_name);
1341f10c 594 if ($inherited_attr->isa('Moose::Meta::Attribute')) {
d7d8a8c7 595 return $inherited_attr->clone_and_inherit_options(%options);
1341f10c 596 }
597 else {
598 # NOTE:
599 # kind of a kludge to handle Class::MOP::Attributes
d7d8a8c7 600 return $inherited_attr->Moose::Meta::Attribute::clone_and_inherit_options(%options);
ac2dc464 601 }
1341f10c 602}
603
5cf3dbcf 604## -------------------------------------------------
605
bf6fa6b3 606our $error_level;
11c86f15 607
608sub throw_error {
609 my ( $self, @args ) = @_;
bf6fa6b3 610 local $error_level = ($error_level || 0) + 1;
11c86f15 611 $self->raise_error($self->create_error(@args));
612}
613
614sub raise_error {
615 my ( $self, @args ) = @_;
616 die @args;
617}
618
619sub create_error {
620 my ( $self, @args ) = @_;
621
18748ad6 622 require Carp::Heavy;
623
bf6fa6b3 624 local $error_level = ($error_level || 0 ) + 1;
18748ad6 625
11c86f15 626 if ( @args % 2 == 1 ) {
627 unshift @args, "message";
628 }
629
fcab1742 630 my %args = ( metaclass => $self, last_error => $@, @args );
11c86f15 631
bf6fa6b3 632 $args{depth} += $error_level;
11c86f15 633
bf6fa6b3 634 my $class = ref $self ? $self->error_class : "Moose::Error::Default";
11c86f15 635
a810a01f 636 Class::MOP::load_class($class);
637
11c86f15 638 $class->new(
bf6fa6b3 639 Carp::caller_info($args{depth}),
640 %args
11c86f15 641 );
642}
643
c0e30cf5 6441;
645
646__END__
647
648=pod
649
650=head1 NAME
651
e522431d 652Moose::Meta::Class - The Moose metaclass
c0e30cf5 653
c0e30cf5 654=head1 DESCRIPTION
655
70bb0f97 656This class is a subclass of L<Class::MOP::Class> that provides
657additional Moose-specific functionality.
e522431d 658
7854b409 659To really understand this class, you will need to start with the
660L<Class::MOP::Class> documentation. This class can be understood as a
661set of additional features on top of the basic feature provided by
662that parent class.
6ba6d68c 663
d4b1449e 664=head1 INHERITANCE
665
666C<Moose::Meta::Class> is a subclass of L<Class::MOP::Class>.
667
c0e30cf5 668=head1 METHODS
669
670=over 4
671
70bb0f97 672=item B<< Moose::Meta::Class->initialize($package_name, %options) >>
590868a3 673
70bb0f97 674This overrides the parent's method in order to provide its own
675defaults for the C<attribute_metaclass>, C<instance_metaclass>, and
676C<method_metaclass> options.
61bdd94f 677
70bb0f97 678These all default to the appropriate Moose class.
61bdd94f 679
70bb0f97 680=item B<< Moose::Meta::Class->create($package_name, %options) >>
17594769 681
70bb0f97 682This overrides the parent's method in order to accept a C<roles>
683option. This should be an array reference containing one more roles
684that the class does.
17594769 685
70bb0f97 686 my $metaclass = Moose::Meta::Class->create( 'New::Class', roles => [...] );
17594769 687
70bb0f97 688=item B<< Moose::Meta::Class->create_anon_class >>
17594769 689
70bb0f97 690This overrides the parent's method to accept a C<roles> option, just
691as C<create> does.
5cf3dbcf 692
70bb0f97 693It also accepts a C<cache> option. If this is true, then the anonymous
694class will be cached based on its superclasses and roles. If an
695existing anonymous class in the cache has the same superclasses and
696roles, it will be reused.
ac2dc464 697
70bb0f97 698 my $metaclass = Moose::Meta::Class->create_anon_class(
699 superclasses => ['Foo'],
700 roles => [qw/Some Roles Go Here/],
701 cache => 1,
702 );
ac2dc464 703
70bb0f97 704=item B<< $metaclass->make_immutable(%options) >>
ac2dc464 705
70bb0f97 706This overrides the parent's method to add a few options. Specifically,
707it uses the Moose-specific constructor and destructor classes, and
708enables inlining the destructor.
8c9d74e7 709
70bb0f97 710Also, since Moose always inlines attributes, it sets the
711C<inline_accessors> option to false.
02a0fb52 712
70bb0f97 713=item B<< $metaclass->new_object(%params) >>
a15dff8d 714
70bb0f97 715This overrides the parent's method in order to add support for
716attribute triggers.
6ba6d68c 717
70bb0f97 718=item B<< $metaclass->add_override_method_modifier($name, $sub) >>
ef1d5f4b 719
70bb0f97 720This adds an C<override> method modifier to the package.
e9ec68d6 721
70bb0f97 722=item B<< $metaclass->add_augment_method_modifier($name, $sub) >>
e9ec68d6 723
70bb0f97 724This adds an C<augment> method modifier to the package.
78cd1d3b 725
70bb0f97 726=item B<< $metaclass->calculate_all_roles >>
02a0fb52 727
70bb0f97 728This will return a unique array of C<Moose::Meta::Role> instances
729which are attached to this class.
78cd1d3b 730
70bb0f97 731=item B<< $metaclass->add_role($role) >>
02a0fb52 732
70bb0f97 733This takes a L<Moose::Meta::Role> object, and adds it to the class's
734list of roles. This I<does not> actually apply the role to the class.
2b14ac61 735
b90dd4ef 736=item B<< $metaclass->role_applications >>
737
639f9a1a 738Returns a list of L<Moose::Meta::Role::Application::ToClass>
b90dd4ef 739objects, which contain the arguments to role application.
740
741=item B<< $metaclass->add_role_application($application) >>
742
743This takes a L<Moose::Meta::Role::Application::ToClass> object, and
744adds it to the class's list of role applications. This I<does not>
745actually apply any role to the class; it is only for tracking role
746applications.
747
70bb0f97 748=item B<< $metaclass->does_role($role_name) >>
ef333f17 749
70bb0f97 750This returns a boolean indicating whether or not the class does the
751specified role. This tests both the class and its parents.
02a0fb52 752
70bb0f97 753=item B<< $metaclass->excludes_role($role_name) >>
ef333f17 754
70bb0f97 755A class excludes a role if it has already composed a role which
756excludes the named role. This tests both the class and its parents.
02a0fb52 757
70bb0f97 758=item B<< $metaclass->add_attribute($attr_name, %params|$params) >>
ef333f17 759
70bb0f97 760This overrides the parent's method in order to allow the parameters to
761be provided as a hash reference.
02a0fb52 762
70bb0f97 763=item B<< $metaclass->constructor_class ($class_name) >>
d79e62fd 764
70bb0f97 765=item B<< $metaclass->destructor_class ($class_name) >>
e606ae5f 766
767These are the names of classes used when making a class
768immutable. These default to L<Moose::Meta::Method::Constructor> and
769L<Moose::Meta::Method::Destructor> respectively. These accessors are
770read-write, so you can use them to change the class name.
771
70bb0f97 772=item B<< $metaclass->error_class($class_name) >>
8b1d510f 773
70bb0f97 774The name of the class used to throw errors. This defaults to
8b1d510f 775L<Moose::Error::Default>, which generates an error with a stacktrace
776just like C<Carp::confess>.
777
70bb0f97 778=item B<< $metaclass->throw_error($message, %extra) >>
11c86f15 779
780Throws the error created by C<create_error> using C<raise_error>
781
c0e30cf5 782=back
783
784=head1 BUGS
785
ac2dc464 786All complex software has bugs lurking in it, and this module is no
c0e30cf5 787exception. If you find a bug please either email me, or add the bug
788to cpan-RT.
789
c0e30cf5 790=head1 AUTHOR
791
792Stevan Little E<lt>stevan@iinteractive.comE<gt>
793
794=head1 COPYRIGHT AND LICENSE
795
2840a3b2 796Copyright 2006-2009 by Infinity Interactive, Inc.
c0e30cf5 797
798L<http://www.iinteractive.com>
799
800This library is free software; you can redistribute it and/or modify
ac2dc464 801it under the same terms as Perl itself.
c0e30cf5 802
8a7a9c53 803=cut
1a563243 804