class_of _reconcile_role_differences
[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 ),
184 $attr
185 );
8c9d74e7 186 }
1308deb4 187
ac2dc464 188 return $self;
8c9d74e7 189}
190
a15dff8d 191sub construct_instance {
e606ae5f 192 my $class = shift;
193 my $params = @_ == 1 ? $_[0] : {@_};
ddd0ec20 194 my $meta_instance = $class->get_meta_instance;
575db57d 195 # FIXME:
196 # the code below is almost certainly incorrect
6549b0d1 197 # but this is foreign inheritance, so we might
ac2dc464 198 # have to kludge it in the end.
e606ae5f 199 my $instance = $params->{'__INSTANCE__'} || $meta_instance->create_instance();
ac2dc464 200 foreach my $attr ($class->compute_all_applicable_attributes()) {
e606ae5f 201 $attr->initialize_instance_slot($meta_instance, $instance, $params);
a15dff8d 202 }
203 return $instance;
204}
205
093b12c2 206### ---------------------------------------------
207
a2eec5e7 208sub add_attribute {
209 my $self = shift;
e472c9a5 210 $self->SUPER::add_attribute(
211 (blessed $_[0] && $_[0]->isa('Class::MOP::Attribute')
212 ? $_[0]
213 : $self->_process_attribute(@_))
214 );
a2eec5e7 215}
216
78cd1d3b 217sub add_override_method_modifier {
218 my ($self, $name, $method, $_super_package) = @_;
18c2ec0e 219
d05cd563 220 (!$self->has_method($name))
11c86f15 221 || $self->throw_error("Cannot add an override method if a local method is already present");
18c2ec0e 222
74862722 223 $self->add_method($name => Moose::Meta::Method::Overridden->new(
3f9e4b0a 224 method => $method,
225 class => $self,
226 package => $_super_package, # need this for roles
227 name => $name,
18c2ec0e 228 ));
78cd1d3b 229}
230
231sub add_augment_method_modifier {
ac2dc464 232 my ($self, $name, $method) = @_;
d05cd563 233 (!$self->has_method($name))
11c86f15 234 || $self->throw_error("Cannot add an augment method if a local method is already present");
3f9e4b0a 235
236 $self->add_method($name => Moose::Meta::Method::Augmented->new(
237 method => $method,
238 class => $self,
239 name => $name,
240 ));
78cd1d3b 241}
242
1341f10c 243## Private Utility methods ...
244
05d9eaf6 245sub _find_next_method_by_name_which_is_not_overridden {
246 my ($self, $name) = @_;
68efb014 247 foreach my $method ($self->find_all_methods_by_name($name)) {
ac2dc464 248 return $method->{code}
74862722 249 if blessed($method->{code}) && !$method->{code}->isa('Moose::Meta::Method::Overridden');
05d9eaf6 250 }
251 return undef;
252}
253
41419b9e 254sub _fix_metaclass_incompatibility {
1341f10c 255 my ($self, @superclasses) = @_;
e606ae5f 256
1341f10c 257 foreach my $super (@superclasses) {
f8b6827f 258 next if $self->_superclass_meta_is_compatible($super);
e606ae5f 259
260 unless ( $self->is_pristine ) {
f8b6827f 261 $self->throw_error(
262 "Cannot attempt to reinitialize metaclass for "
263 . $self->name
264 . ", it isn't pristine" );
1341f10c 265 }
e606ae5f 266
0635500e 267 $self->_reconcile_with_superclass_meta($super);
f8b6827f 268 }
f8b6827f 269}
270
271sub _superclass_meta_is_compatible {
272 my ($self, $super) = @_;
273
274 my $super_meta = Class::MOP::Class->initialize($super)
275 or return 1;
276
277 next unless $super_meta->isa("Class::MOP::Class");
278
279 my $super_meta_name
280 = $super_meta->is_immutable
281 ? $super_meta->get_mutable_metaclass_name
282 : ref($super_meta);
283
284 return 1
285 if $self->isa($super_meta_name)
286 and
287 $self->instance_metaclass->isa( $super_meta->instance_metaclass );
288}
289
290# I don't want to have to type this >1 time
291my @MetaClassTypes =
8b1d510f 292 qw( attribute_metaclass method_metaclass instance_metaclass
293 constructor_class destructor_class error_class );
f8b6827f 294
295sub _reconcile_with_superclass_meta {
296 my ($self, $super) = @_;
297
29782f74 298 my $super_meta = Class::MOP::class_of($super);
f8b6827f 299
dd37a5be 300 my $super_meta_name
f8b6827f 301 = $super_meta->is_immutable
302 ? $super_meta->get_mutable_metaclass_name
303 : ref($super_meta);
e606ae5f 304
f8b6827f 305 my $self_metaclass = ref $self;
306
307 # If neither of these is true we have a more serious
308 # incompatibility that we just cannot fix (yet?).
dd37a5be 309 if ( $super_meta_name->isa( ref $self )
f8b6827f 310 && all { $super_meta->$_->isa( $self->$_ ) } @MetaClassTypes ) {
0635500e 311 $self->_reinitialize_with($super_meta);
f8b6827f 312 }
313 elsif ( $self->_all_metaclasses_differ_by_roles_only($super_meta) ) {
0635500e 314 $self->_reconcile_role_differences($super_meta);
1341f10c 315 }
1341f10c 316}
317
f8b6827f 318sub _reinitialize_with {
319 my ( $self, $new_meta ) = @_;
320
0635500e 321 my $new_self = $new_meta->reinitialize(
f8b6827f 322 $self->name,
323 attribute_metaclass => $new_meta->attribute_metaclass,
324 method_metaclass => $new_meta->method_metaclass,
325 instance_metaclass => $new_meta->instance_metaclass,
326 );
327
8b1d510f 328 $new_self->$_( $new_meta->$_ )
329 for qw( constructor_class destructor_class error_class );
f8b6827f 330
0635500e 331 %$self = %$new_self;
332
333 bless $self, ref $new_self;
334
4c5fcc12 335 # We need to replace the cached metaclass instance or else when it
336 # goes out of scope Class::MOP::Class destroy's the namespace for
337 # the metaclass's class, causing much havoc.
0635500e 338 Class::MOP::store_metaclass_by_name( $self->name, $self );
4c5fcc12 339 Class::MOP::weaken_metaclass( $self->name ) if $self->is_anon_class;
f8b6827f 340}
341
342# In the more complex case, we share a common ancestor with our
343# superclass's metaclass, but each metaclass (ours and the parent's)
344# has a different set of roles applied. We reconcile this by first
345# reinitializing into the parent class, and _then_ applying our own
346# roles.
347sub _all_metaclasses_differ_by_roles_only {
348 my ($self, $super_meta) = @_;
349
350 for my $pair (
351 [ ref $self, ref $super_meta ],
352 map { [ $self->$_, $super_meta->$_ ] } @MetaClassTypes
353 ) {
354
355 next if $pair->[0] eq $pair->[1];
356
357 my $self_meta_meta = Class::MOP::Class->initialize( $pair->[0] );
358 my $super_meta_meta = Class::MOP::Class->initialize( $pair->[1] );
359
360 my $common_ancestor
361 = _find_common_ancestor( $self_meta_meta, $super_meta_meta );
362
363 return unless $common_ancestor;
364
365 return
366 unless _is_role_only_subclass_of(
367 $self_meta_meta,
368 $common_ancestor,
369 )
370 && _is_role_only_subclass_of(
371 $super_meta_meta,
372 $common_ancestor,
373 );
374 }
375
376 return 1;
377}
378
379# This, and some other functions, could be called as methods, but
380# they're not for two reasons. One, we just end up ignoring the first
381# argument, because we can't call these directly on one of the real
382# arguments, because one of them could be a Class::MOP::Class object
383# and not a Moose::Meta::Class. Second, only a completely insane
384# person would attempt to subclass this stuff!
385sub _find_common_ancestor {
386 my ($meta1, $meta2) = @_;
387
388 # FIXME? This doesn't account for multiple inheritance (not sure
389 # if it needs to though). For example, is somewhere in $meta1's
db9fda52 390 # history it inherits from both ClassA and ClassB, and $meta2
f8b6827f 391 # inherits from ClassB & ClassA, does it matter? And what crazy
392 # fool would do that anyway?
393
394 my %meta1_parents = map { $_ => 1 } $meta1->linearized_isa;
395
396 return first { $meta1_parents{$_} } $meta2->linearized_isa;
397}
398
399sub _is_role_only_subclass_of {
400 my ($meta, $ancestor) = @_;
401
402 return 1 if $meta->name eq $ancestor;
403
404 my @roles = _all_roles_until( $meta, $ancestor );
405
406 my %role_packages = map { $_->name => 1 } @roles;
407
408 my $ancestor_meta = Class::MOP::Class->initialize($ancestor);
409
410 my %shared_ancestors = map { $_ => 1 } $ancestor_meta->linearized_isa;
411
412 for my $method ( $meta->get_all_methods() ) {
413 next if $method->name eq 'meta';
414 next if $method->can('associated_attribute');
415
416 next
417 if $role_packages{ $method->original_package_name }
418 || $shared_ancestors{ $method->original_package_name };
419
420 return 0;
421 }
422
423 # FIXME - this really isn't right. Just because an attribute is
424 # defined in a role doesn't mean it isn't _also_ defined in the
425 # subclass.
426 for my $attr ( $meta->get_all_attributes ) {
427 next if $shared_ancestors{ $attr->associated_class->name };
428
429 next if any { $_->has_attribute( $attr->name ) } @roles;
430
431 return 0;
432 }
433
434 return 1;
435}
436
437sub _all_roles {
438 my $meta = shift;
439
440 return _all_roles_until($meta);
441}
442
443sub _all_roles_until {
444 my ($meta, $stop_at_class) = @_;
445
446 return unless $meta->can('calculate_all_roles');
447
448 my @roles = $meta->calculate_all_roles;
449
450 for my $class ( $meta->linearized_isa ) {
451 last if $stop_at_class && $stop_at_class eq $class;
452
453 my $meta = Class::MOP::Class->initialize($class);
454 last unless $meta->can('calculate_all_roles');
455
456 push @roles, $meta->calculate_all_roles;
457 }
458
8b1d510f 459 return uniq @roles;
f8b6827f 460}
461
462sub _reconcile_role_differences {
463 my ($self, $super_meta) = @_;
464
3897e146 465 my $self_meta = Class::MOP::class_of($self);
f8b6827f 466
467 my %roles;
468
469 if ( my @roles = map { $_->name } _all_roles($self_meta) ) {
470 $roles{metaclass_roles} = \@roles;
471 }
472
473 for my $thing (@MetaClassTypes) {
474 my $name = $self->$thing();
475
476 my $thing_meta = Class::MOP::Class->initialize($name);
477
478 my @roles = map { $_->name } _all_roles($thing_meta)
479 or next;
480
481 $roles{ $thing . '_roles' } = \@roles;
482 }
483
2b72f3b4 484 $self->_reinitialize_with($super_meta);
f8b6827f 485
486 Moose::Util::MetaRole::apply_metaclass_roles(
487 for_class => $self->name,
488 %roles,
489 );
490
491 return $self;
492}
493
d7d8a8c7 494# NOTE:
d9bb6c63 495# this was crap anyway, see
496# Moose::Util::apply_all_roles
d7d8a8c7 497# instead
4498537c 498sub _apply_all_roles {
547dda77 499 Carp::croak 'DEPRECATED: use Moose::Util::apply_all_roles($meta, @roles) instead'
4498537c 500}
1341f10c 501
502sub _process_attribute {
a3738e5b 503 my ( $self, $name, @args ) = @_;
7e59b803 504
505 @args = %{$args[0]} if scalar @args == 1 && ref($args[0]) eq 'HASH';
d9bb6c63 506
f9b5f5f8 507 if (($name || '') =~ /^\+(.*)/) {
7e59b803 508 return $self->_process_inherited_attribute($1, @args);
1341f10c 509 }
510 else {
7e59b803 511 return $self->_process_new_attribute($name, @args);
512 }
513}
514
515sub _process_new_attribute {
516 my ( $self, $name, @args ) = @_;
7e59b803 517
d5c30e52 518 $self->attribute_metaclass->interpolate_class_and_new($name, @args);
1341f10c 519}
520
521sub _process_inherited_attribute {
522 my ($self, $attr_name, %options) = @_;
523 my $inherited_attr = $self->find_attribute_by_name($attr_name);
524 (defined $inherited_attr)
329c5dd4 525 || $self->throw_error("Could not find an attribute by the name of '$attr_name' to inherit from in ${\$self->name}", data => $attr_name);
1341f10c 526 if ($inherited_attr->isa('Moose::Meta::Attribute')) {
d7d8a8c7 527 return $inherited_attr->clone_and_inherit_options(%options);
1341f10c 528 }
529 else {
530 # NOTE:
531 # kind of a kludge to handle Class::MOP::Attributes
d7d8a8c7 532 return $inherited_attr->Moose::Meta::Attribute::clone_and_inherit_options(%options);
ac2dc464 533 }
1341f10c 534}
535
5cf3dbcf 536## -------------------------------------------------
537
538use Moose::Meta::Method::Constructor;
1f779926 539use Moose::Meta::Method::Destructor;
5cf3dbcf 540
ac2dc464 541
70695d9c 542sub _default_immutable_transformer_options {
ac2dc464 543 my $self = shift;
70695d9c 544
545 my %options = $self->SUPER::_default_immutable_transformer_options;
546
547 # We need to copy the references as we do not want to alter the
548 # superclass's references.
549 $options{cannot_call} = [ @{ $options{cannot_call} }, 'add_role' ];
550 $options{memoize} = {
551 %{ $options{memoize} },
552 calculate_all_roles => 'ARRAY',
553 };
554
555 %options = (
556 %options,
557 constructor_class => $self->constructor_class,
558 destructor_class => $self->destructor_class,
559 inline_destructor => 1,
560
561 # Moose always does this when an attribute is created
562 inline_accessors => 0,
563 );
564
565 return %options
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