rename 'error' error parameter to 'last_error'
[gitmo/Moose.git] / lib / Moose / Meta / Class.pm
1
2 package Moose::Meta::Class;
3
4 use strict;
5 use warnings;
6
7 use Class::MOP;
8
9 use Carp ();
10 use List::Util qw( first );
11 use List::MoreUtils qw( any all );
12 use Scalar::Util 'weaken', 'blessed';
13
14 our $VERSION   = '0.57';
15 $VERSION = eval $VERSION;
16 our $AUTHORITY = 'cpan:STEVAN';
17
18 use Moose::Meta::Method::Overriden;
19 use Moose::Meta::Method::Augmented;
20 use Moose::Error::Default;
21
22 use base 'Class::MOP::Class';
23
24 __PACKAGE__->meta->add_attribute('roles' => (
25     reader  => 'roles',
26     default => sub { [] }
27 ));
28
29 __PACKAGE__->meta->add_attribute('constructor_class' => (
30     accessor => 'constructor_class',
31     default  => sub { 'Moose::Meta::Method::Constructor' }
32 ));
33
34 __PACKAGE__->meta->add_attribute('destructor_class' => (
35     accessor => 'destructor_class',
36     default  => sub { 'Moose::Meta::Method::Destructor' }
37 ));
38
39 __PACKAGE__->meta->add_attribute('error_class' => (
40     accessor => 'error_class',
41     default  => 'Moose::Error::Default',
42 ));
43
44
45 sub initialize {
46     my $class = shift;
47     my $pkg   = shift;
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             );    
55 }
56
57 sub create {
58     my ($self, $package_name, %options) = @_;
59     
60     (ref $options{roles} eq 'ARRAY')
61         || $self->throw_error("You must pass an ARRAY ref of roles", data => $options{roles})
62             if exists $options{roles};
63
64     my $class = $self->SUPER::create($package_name, %options);
65
66     if (exists $options{roles}) {
67         Moose::Util::apply_all_roles($class, @{$options{roles}});
68     }
69     
70     return $class;
71 }
72
73 sub check_metaclass_compatibility {
74     my $self = shift;
75
76     if ( my @supers = $self->superclasses ) {
77         $self->_fix_metaclass_incompatibility(@supers);
78     }
79
80     $self->SUPER::check_metaclass_compatibility(@_);
81 }
82
83 my %ANON_CLASSES;
84
85 sub create_anon_class {
86     my ($self, %options) = @_;
87
88     my $cache_ok = delete $options{cache};
89     
90     # something like Super::Class|Super::Class::2=Role|Role::1
91     my $cache_key = join '=' => (
92         join('|', sort @{$options{superclasses} || []}),
93         join('|', sort @{$options{roles}        || []}),
94     );
95     
96     if ($cache_ok && defined $ANON_CLASSES{$cache_key}) {
97         return $ANON_CLASSES{$cache_key};
98     }
99     
100     my $new_class = $self->SUPER::create_anon_class(%options);
101
102     $ANON_CLASSES{$cache_key} = $new_class
103         if $cache_ok;
104
105     return $new_class;
106 }
107
108 sub add_role {
109     my ($self, $role) = @_;
110     (blessed($role) && $role->isa('Moose::Meta::Role'))
111         || $self->throw_error("Roles must be instances of Moose::Meta::Role", data => $role);
112     push @{$self->roles} => $role;
113 }
114
115 sub calculate_all_roles {
116     my $self = shift;
117     my %seen;
118     grep { !$seen{$_->name}++ } map { $_->calculate_all_roles } @{ $self->roles };
119 }
120
121 sub does_role {
122     my ($self, $role_name) = @_;
123     (defined $role_name)
124         || $self->throw_error("You must supply a role name to look for");
125     foreach my $class ($self->class_precedence_list) {
126         next unless $class->can('meta') && $class->meta->can('roles');
127         foreach my $role (@{$class->meta->roles}) {
128             return 1 if $role->does_role($role_name);
129         }
130     }
131     return 0;
132 }
133
134 sub excludes_role {
135     my ($self, $role_name) = @_;
136     (defined $role_name)
137         || $self->throw_error("You must supply a role name to look for");
138     foreach my $class ($self->class_precedence_list) {
139         next unless $class->can('meta');
140         # NOTE:
141         # in the pretty rare instance when a Moose metaclass
142         # is itself extended with a role, this check needs to
143         # be done since some items in the class_precedence_list
144         # might in fact be Class::MOP based still.
145         next unless $class->meta->can('roles');
146         foreach my $role (@{$class->meta->roles}) {
147             return 1 if $role->excludes_role($role_name);
148         }
149     }
150     return 0;
151 }
152
153 sub new_object {
154     my $class = shift;
155     my $params = @_ == 1 ? $_[0] : {@_};
156     my $self = $class->SUPER::new_object($params);
157     foreach my $attr ($class->compute_all_applicable_attributes()) {
158         # if we have a trigger, then ...
159         if ($attr->can('has_trigger') && $attr->has_trigger) {
160             # make sure we have an init-arg ...
161             if (defined(my $init_arg = $attr->init_arg)) {
162                 # now make sure an init-arg was passes ...
163                 if (exists $params->{$init_arg}) {
164                     # and if get here, fire the trigger
165                     $attr->trigger->(
166                         $self, 
167                         # check if there is a coercion
168                         ($attr->should_coerce
169                             # and if so, we need to grab the 
170                             # value that is actually been stored
171                             ? $attr->get_read_method_ref->($self)
172                             # otherwise, just get the value from
173                             # the constructor params
174                             : $params->{$init_arg}), 
175                         $attr
176                     );
177                 }
178             }       
179         }
180     }
181     return $self;
182 }
183
184 sub construct_instance {
185     my $class = shift;
186     my $params = @_ == 1 ? $_[0] : {@_};
187     my $meta_instance = $class->get_meta_instance;
188     # FIXME:
189     # the code below is almost certainly incorrect
190     # but this is foreign inheritence, so we might
191     # have to kludge it in the end.
192     my $instance = $params->{'__INSTANCE__'} || $meta_instance->create_instance();
193     foreach my $attr ($class->compute_all_applicable_attributes()) {
194         $attr->initialize_instance_slot($meta_instance, $instance, $params);
195     }
196     return $instance;
197 }
198
199 # FIXME:
200 # This is ugly
201 sub get_method_map {
202     my $self = shift;
203
204     my $current = Class::MOP::check_package_cache_flag($self->name);
205
206     if (defined $self->{'_package_cache_flag'} && $self->{'_package_cache_flag'} == $current) {
207         return $self->{'methods'};
208     }
209
210     $self->{_package_cache_flag} = $current;
211
212     my $map  = $self->{'methods'};
213
214     my $class_name       = $self->name;
215     my $method_metaclass = $self->method_metaclass;
216
217     my %all_code = $self->get_all_package_symbols('CODE');
218
219     foreach my $symbol (keys %all_code) {
220         my $code = $all_code{$symbol};
221
222         next if exists  $map->{$symbol} &&
223                 defined $map->{$symbol} &&
224                         $map->{$symbol}->body == $code;
225
226         my ($pkg, $name) = Class::MOP::get_code_info($code);
227
228         if ($pkg->can('meta')
229             # NOTE:
230             # we don't know what ->meta we are calling
231             # here, so we need to be careful cause it
232             # just might blow up at us, or just complain
233             # loudly (in the case of Curses.pm) so we
234             # just be a little overly cautious here.
235             # - SL
236             && eval { no warnings; blessed($pkg->meta) }
237             && $pkg->meta->isa('Moose::Meta::Role')) {
238             #my $role = $pkg->meta->name;
239             #next unless $self->does_role($role);
240         }
241         else {
242             
243             # NOTE:
244             # in 5.10 constant.pm the constants show up 
245             # as being in the right package, but in pre-5.10
246             # they show up as constant::__ANON__ so we 
247             # make an exception here to be sure that things
248             # work as expected in both.
249             # - SL
250             unless ($pkg eq 'constant' && $name eq '__ANON__') {
251                 next if ($pkg  || '') ne $class_name ||
252                         (($name || '') ne '__ANON__' && ($pkg  || '') ne $class_name);
253             }
254
255         }
256
257         $map->{$symbol} = $method_metaclass->wrap(
258             $code,
259             package_name => $class_name,
260             name         => $symbol
261         );
262     }
263
264     return $map;
265 }
266
267 ### ---------------------------------------------
268
269 sub add_attribute {
270     my $self = shift;
271     $self->SUPER::add_attribute(
272         (blessed $_[0] && $_[0]->isa('Class::MOP::Attribute')
273             ? $_[0] 
274             : $self->_process_attribute(@_))    
275     );
276 }
277
278 sub add_override_method_modifier {
279     my ($self, $name, $method, $_super_package) = @_;
280
281     (!$self->has_method($name))
282         || $self->throw_error("Cannot add an override method if a local method is already present");
283
284     $self->add_method($name => Moose::Meta::Method::Overriden->new(
285         method  => $method,
286         class   => $self,
287         package => $_super_package, # need this for roles
288         name    => $name,
289     ));
290 }
291
292 sub add_augment_method_modifier {
293     my ($self, $name, $method) = @_;
294     (!$self->has_method($name))
295         || $self->throw_error("Cannot add an augment method if a local method is already present");
296
297     $self->add_method($name => Moose::Meta::Method::Augmented->new(
298         method  => $method,
299         class   => $self,
300         name    => $name,
301     ));
302 }
303
304 ## Private Utility methods ...
305
306 sub _find_next_method_by_name_which_is_not_overridden {
307     my ($self, $name) = @_;
308     foreach my $method ($self->find_all_methods_by_name($name)) {
309         return $method->{code}
310             if blessed($method->{code}) && !$method->{code}->isa('Moose::Meta::Method::Overriden');
311     }
312     return undef;
313 }
314
315 sub _fix_metaclass_incompatibility {
316     my ($self, @superclasses) = @_;
317
318     foreach my $super (@superclasses) {
319         next if $self->_superclass_meta_is_compatible($super);
320
321         unless ( $self->is_pristine ) {
322             $self->throw_error(
323                       "Cannot attempt to reinitialize metaclass for "
324                     . $self->name
325                     . ", it isn't pristine" );
326         }
327
328         $self->_reconcile_with_superclass_meta($super);
329     }
330 }
331
332 sub _superclass_meta_is_compatible {
333     my ($self, $super) = @_;
334
335     my $super_meta = Class::MOP::Class->initialize($super)
336         or return 1;
337
338     next unless $super_meta->isa("Class::MOP::Class");
339
340     my $super_meta_name
341         = $super_meta->is_immutable
342         ? $super_meta->get_mutable_metaclass_name
343         : ref($super_meta);
344
345     return 1
346         if $self->isa($super_meta_name)
347             and
348            $self->instance_metaclass->isa( $super_meta->instance_metaclass );
349 }
350
351 # I don't want to have to type this >1 time
352 my @MetaClassTypes =
353     qw( attribute_metaclass method_metaclass instance_metaclass constructor_class destructor_class );
354
355 sub _reconcile_with_superclass_meta {
356     my ($self, $super) = @_;
357
358     my $super_meta = $super->meta;
359
360     my $super_meta_name
361         = $super_meta->is_immutable
362         ? $super_meta->get_mutable_metaclass_name
363         : ref($super_meta);
364
365     my $self_metaclass = ref $self;
366
367     # If neither of these is true we have a more serious
368     # incompatibility that we just cannot fix (yet?).
369     if ( $super_meta_name->isa( ref $self )
370         && all { $super_meta->$_->isa( $self->$_ ) } @MetaClassTypes ) {
371         $self->_reinitialize_with($super_meta);
372     }
373     elsif ( $self->_all_metaclasses_differ_by_roles_only($super_meta) ) {
374         $self->_reconcile_role_differences($super_meta);
375     }
376 }
377
378 sub _reinitialize_with {
379     my ( $self, $new_meta ) = @_;
380
381     my $new_self = $new_meta->reinitialize(
382         $self->name,
383         attribute_metaclass => $new_meta->attribute_metaclass,
384         method_metaclass    => $new_meta->method_metaclass,
385         instance_metaclass  => $new_meta->instance_metaclass,
386     );
387
388     $new_self->$_( $new_meta->$_ ) for qw( constructor_class destructor_class );
389
390     %$self = %$new_self;
391
392     bless $self, ref $new_self;
393
394     # We need to replace the cached metaclass instance or else when it
395     # goes out of scope Class::MOP::Class destroy's the namespace for
396     # the metaclass's class, causing much havoc.
397     Class::MOP::store_metaclass_by_name( $self->name, $self );
398     Class::MOP::weaken_metaclass( $self->name ) if $self->is_anon_class;
399 }
400
401 # In the more complex case, we share a common ancestor with our
402 # superclass's metaclass, but each metaclass (ours and the parent's)
403 # has a different set of roles applied. We reconcile this by first
404 # reinitializing into the parent class, and _then_ applying our own
405 # roles.
406 sub _all_metaclasses_differ_by_roles_only {
407     my ($self, $super_meta) = @_;
408
409     for my $pair (
410         [ ref $self, ref $super_meta ],
411         map { [ $self->$_, $super_meta->$_ ] } @MetaClassTypes
412         ) {
413
414         next if $pair->[0] eq $pair->[1];
415
416         my $self_meta_meta  = Class::MOP::Class->initialize( $pair->[0] );
417         my $super_meta_meta = Class::MOP::Class->initialize( $pair->[1] );
418
419         my $common_ancestor
420             = _find_common_ancestor( $self_meta_meta, $super_meta_meta );
421
422         return unless $common_ancestor;
423
424         return
425             unless _is_role_only_subclass_of(
426             $self_meta_meta,
427             $common_ancestor,
428             )
429             && _is_role_only_subclass_of(
430             $super_meta_meta,
431             $common_ancestor,
432             );
433     }
434
435     return 1;
436 }
437
438 # This, and some other functions, could be called as methods, but
439 # they're not for two reasons. One, we just end up ignoring the first
440 # argument, because we can't call these directly on one of the real
441 # arguments, because one of them could be a Class::MOP::Class object
442 # and not a Moose::Meta::Class. Second, only a completely insane
443 # person would attempt to subclass this stuff!
444 sub _find_common_ancestor {
445     my ($meta1, $meta2) = @_;
446
447     # FIXME? This doesn't account for multiple inheritance (not sure
448     # if it needs to though). For example, is somewhere in $meta1's
449     # history it inherits from both ClassA and ClassB, and $meta
450     # inherits from ClassB & ClassA, does it matter? And what crazy
451     # fool would do that anyway?
452
453     my %meta1_parents = map { $_ => 1 } $meta1->linearized_isa;
454
455     return first { $meta1_parents{$_} } $meta2->linearized_isa;
456 }
457
458 sub _is_role_only_subclass_of {
459     my ($meta, $ancestor) = @_;
460
461     return 1 if $meta->name eq $ancestor;
462
463     my @roles = _all_roles_until( $meta, $ancestor );
464
465     my %role_packages = map { $_->name => 1 } @roles;
466
467     my $ancestor_meta = Class::MOP::Class->initialize($ancestor);
468
469     my %shared_ancestors = map { $_ => 1 } $ancestor_meta->linearized_isa;
470
471     for my $method ( $meta->get_all_methods() ) {
472         next if $method->name eq 'meta';
473         next if $method->can('associated_attribute');
474
475         next
476             if $role_packages{ $method->original_package_name }
477                 || $shared_ancestors{ $method->original_package_name };
478
479         return 0;
480     }
481
482     # FIXME - this really isn't right. Just because an attribute is
483     # defined in a role doesn't mean it isn't _also_ defined in the
484     # subclass.
485     for my $attr ( $meta->get_all_attributes ) {
486         next if $shared_ancestors{ $attr->associated_class->name };
487
488         next if any { $_->has_attribute( $attr->name ) } @roles;
489
490         return 0;
491     }
492
493     return 1;
494 }
495
496 sub _all_roles {
497     my $meta = shift;
498
499     return _all_roles_until($meta);
500 }
501
502 sub _all_roles_until {
503     my ($meta, $stop_at_class) = @_;
504
505     return unless $meta->can('calculate_all_roles');
506
507     my @roles = $meta->calculate_all_roles;
508
509     for my $class ( $meta->linearized_isa ) {
510         last if $stop_at_class && $stop_at_class eq $class;
511
512         my $meta = Class::MOP::Class->initialize($class);
513         last unless $meta->can('calculate_all_roles');
514
515         push @roles, $meta->calculate_all_roles;
516     }
517
518     return @roles;
519 }
520
521 sub _reconcile_role_differences {
522     my ($self, $super_meta) = @_;
523
524     my $self_meta = $self->meta;
525
526     my %roles;
527
528     if ( my @roles = map { $_->name } _all_roles($self_meta) ) {
529         $roles{metaclass_roles} = \@roles;
530     }
531
532     for my $thing (@MetaClassTypes) {
533         my $name = $self->$thing();
534
535         my $thing_meta = Class::MOP::Class->initialize($name);
536
537         my @roles = map { $_->name } _all_roles($thing_meta)
538             or next;
539
540         $roles{ $thing . '_roles' } = \@roles;
541     }
542
543     $self->_reinitialize_with($super_meta);
544
545     Moose::Util::MetaRole::apply_metaclass_roles(
546         for_class => $self->name,
547         %roles,
548     );
549
550     return $self;
551 }
552
553 # NOTE:
554 # this was crap anyway, see
555 # Moose::Util::apply_all_roles
556 # instead
557 sub _apply_all_roles { 
558     Carp::croak 'DEPRECATED: use Moose::Util::apply_all_roles($meta, @roles) instead' 
559 }
560
561 sub _process_attribute {
562     my ( $self, $name, @args ) = @_;
563
564     @args = %{$args[0]} if scalar @args == 1 && ref($args[0]) eq 'HASH';
565
566     if ($name =~ /^\+(.*)/) {
567         return $self->_process_inherited_attribute($1, @args);
568     }
569     else {
570         return $self->_process_new_attribute($name, @args);
571     }
572 }
573
574 sub _process_new_attribute {
575     my ( $self, $name, @args ) = @_;
576
577     $self->attribute_metaclass->interpolate_class_and_new($name, @args);
578 }
579
580 sub _process_inherited_attribute {
581     my ($self, $attr_name, %options) = @_;
582     my $inherited_attr = $self->find_attribute_by_name($attr_name);
583     (defined $inherited_attr)
584         || $self->throw_error("Could not find an attribute by the name of '$attr_name' to inherit from", data => $attr_name);
585     if ($inherited_attr->isa('Moose::Meta::Attribute')) {
586         return $inherited_attr->clone_and_inherit_options(%options);
587     }
588     else {
589         # NOTE:
590         # kind of a kludge to handle Class::MOP::Attributes
591         return $inherited_attr->Moose::Meta::Attribute::clone_and_inherit_options(%options);
592     }
593 }
594
595 ## -------------------------------------------------
596
597 use Moose::Meta::Method::Constructor;
598 use Moose::Meta::Method::Destructor;
599
600 # This could be done by using SUPER and altering ->options
601 # I am keeping it this way to make it more explicit.
602 sub create_immutable_transformer {
603     my $self = shift;
604     my $class = Class::MOP::Immutable->new($self, {
605        read_only   => [qw/superclasses/],
606        cannot_call => [qw/
607            add_method
608            alias_method
609            remove_method
610            add_attribute
611            remove_attribute
612            remove_package_symbol
613            add_role
614        /],
615        memoize     => {
616            class_precedence_list             => 'ARRAY',
617            linearized_isa                    => 'ARRAY', # FIXME perl 5.10 memoizes this on its own, no need?
618            get_all_methods                   => 'ARRAY',
619            #get_all_attributes               => 'ARRAY', # it's an alias, no need, but maybe in the future
620            compute_all_applicable_attributes => 'ARRAY',
621            get_meta_instance                 => 'SCALAR',
622            get_method_map                    => 'SCALAR',
623            calculate_all_roles               => 'ARRAY',
624        },
625        # NOTE:
626        # this is ugly, but so are typeglobs, 
627        # so whattayahgonnadoboutit
628        # - SL
629        wrapped => { 
630            add_package_symbol => sub {
631                my $original = shift;
632                $self->throw_error("Cannot add package symbols to an immutable metaclass")
633                    unless (caller(2))[3] eq 'Class::MOP::Package::get_package_symbol'; 
634                goto $original->body;
635            },
636        },       
637     });
638     return $class;
639 }
640
641 sub make_immutable {
642     my $self = shift;
643     $self->SUPER::make_immutable
644       (
645        constructor_class => $self->constructor_class,
646        destructor_class  => $self->destructor_class,
647        inline_destructor => 1,
648        # NOTE:
649        # no need to do this,
650        # Moose always does it
651        inline_accessors  => 0,
652        @_,
653       );
654 }
655
656 #{ package Moose::Meta::Class::ErrorRoutines; %Carp::Internal?
657
658 our $error_level;
659
660 sub throw_error {
661     my ( $self, @args ) = @_;
662     local $error_level = ($error_level || 0) + 1;
663     $self->raise_error($self->create_error(@args));
664 }
665
666 sub raise_error {
667     my ( $self, @args ) = @_;
668     die @args;
669 }
670
671 sub create_error {
672     my ( $self, @args ) = @_;
673
674     require Carp::Heavy;
675
676     local $error_level = ($error_level || 0 ) + 1;
677
678     if ( @args % 2 == 1 ) {
679         unshift @args, "message";
680     }
681
682     my %args = ( metaclass => $self, last_error => $@, @args );
683
684     $args{depth} += $error_level;
685
686     my $class = ref $self ? $self->error_class : "Moose::Error::Default";
687
688     $class->new(
689         Carp::caller_info($args{depth}),
690         %args
691     );
692 }
693
694 1;
695
696 __END__
697
698 =pod
699
700 =head1 NAME
701
702 Moose::Meta::Class - The Moose metaclass
703
704 =head1 DESCRIPTION
705
706 This is a subclass of L<Class::MOP::Class> with Moose specific
707 extensions.
708
709 For the most part, the only time you will ever encounter an
710 instance of this class is if you are doing some serious deep
711 introspection. To really understand this class, you need to refer
712 to the L<Class::MOP::Class> documentation.
713
714 =head1 METHODS
715
716 =over 4
717
718 =item B<initialize>
719
720 =item B<create>
721
722 Overrides original to accept a list of roles to apply to
723 the created class.
724
725    my $metaclass = Moose::Meta::Class->create( 'New::Class', roles => [...] );
726
727 =item B<create_anon_class>
728
729 Overrides original to support roles and caching.
730
731    my $metaclass = Moose::Meta::Class->create_anon_class(
732        superclasses => ['Foo'],
733        roles        => [qw/Some Roles Go Here/],
734        cache        => 1,
735    );
736
737 =item B<make_immutable>
738
739 Override original to add default options for inlining destructor
740 and altering the Constructor metaclass.
741
742 =item B<create_immutable_transformer>
743
744 Override original to lock C<add_role> and memoize C<calculate_all_roles>
745
746 =item B<new_object>
747
748 We override this method to support the C<trigger> attribute option.
749
750 =item B<construct_instance>
751
752 This provides some Moose specific extensions to this method, you
753 almost never call this method directly unless you really know what
754 you are doing.
755
756 This method makes sure to handle the moose weak-ref, type-constraint
757 and type coercion features.
758
759 =item B<get_method_map>
760
761 This accommodates Moose::Meta::Role::Method instances, which are
762 aliased, instead of added, but still need to be counted as valid
763 methods.
764
765 =item B<add_override_method_modifier ($name, $method)>
766
767 This will create an C<override> method modifier for you, and install
768 it in the package.
769
770 =item B<add_augment_method_modifier ($name, $method)>
771
772 This will create an C<augment> method modifier for you, and install
773 it in the package.
774
775 =item B<calculate_all_roles>
776
777 =item B<roles>
778
779 This will return an array of C<Moose::Meta::Role> instances which are
780 attached to this class.
781
782 =item B<add_role ($role)>
783
784 This takes an instance of C<Moose::Meta::Role> in C<$role>, and adds it
785 to the list of associated roles.
786
787 =item B<does_role ($role_name)>
788
789 This will test if this class C<does> a given C<$role_name>. It will
790 not only check it's local roles, but ask them as well in order to
791 cascade down the role hierarchy.
792
793 =item B<excludes_role ($role_name)>
794
795 This will test if this class C<excludes> a given C<$role_name>. It will
796 not only check it's local roles, but ask them as well in order to
797 cascade down the role hierarchy.
798
799 =item B<add_attribute ($attr_name, %params|$params)>
800
801 This method does the same thing as L<Class::MOP::Class::add_attribute>, but adds
802 support for taking the C<$params> as a HASH ref.
803
804 =item B<constructor_class ($class_name)>
805
806 =item B<destructor_class ($class_name)>
807
808 These are the names of classes used when making a class
809 immutable. These default to L<Moose::Meta::Method::Constructor> and
810 L<Moose::Meta::Method::Destructor> respectively. These accessors are
811 read-write, so you can use them to change the class name.
812
813 =item B<check_metaclass_compatibility>
814
815 Moose overrides this method from C<Class::MOP::Class> and attempts to
816 fix some incompatibilities before doing the check.
817
818 =item B<throw_error $message, %extra>
819
820 Throws the error created by C<create_error> using C<raise_error>
821
822 =item B<create_error $message, %extra>
823
824 Creates an error message or object.
825
826 The default behavior is C<create_error_confess>.
827
828 If C<error_class> is set uses C<create_error_object>. Otherwise uses
829 C<error_builder> (a code reference or variant name), and calls the appropriate
830 C<create_error_$builder> method.
831
832 =item B<error_builder $builder_name>
833
834 Get or set the error builder. Defaults to C<confess>.
835
836 =item B<error_class $class_name>
837
838 Get or set the error class. Has no default.
839
840 =item B<create_error_confess %args>
841
842 Creates an error using L<Carp/longmess>
843
844 =item B<create_error_croak %args>
845
846 Creates an error using L<Carp/shortmess>
847
848 =item B<create_error_object %args>
849
850 Calls C<new> on the C<class> parameter in C<%args>. Usable with C<error_class>
851 to support custom error objects for your meta class.
852
853 =item B<raise_error $error>
854
855 Dies with an error object or string.
856
857 =back
858
859 =head1 BUGS
860
861 All complex software has bugs lurking in it, and this module is no
862 exception. If you find a bug please either email me, or add the bug
863 to cpan-RT.
864
865 =head1 AUTHOR
866
867 Stevan Little E<lt>stevan@iinteractive.comE<gt>
868
869 =head1 COPYRIGHT AND LICENSE
870
871 Copyright 2006-2008 by Infinity Interactive, Inc.
872
873 L<http://www.iinteractive.com>
874
875 This library is free software; you can redistribute it and/or modify
876 it under the same terms as Perl itself.
877
878 =cut
879