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