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