Tenative switch to a generated DEMOLISHALL - see rest of message for caveats
[gitmo/Role-Tiny.git] / lib / Moo / Object.pm
1 package Moo::Object;
2
3 use strictures 1;
4
5 our %NO_BUILD;
6 our $BUILD_MAKER;
7 our $DEMOLISH_MAKER;
8
9 sub new {
10   my $class = shift;
11   $NO_BUILD{$class} and
12     return bless({ ref($_[0]) eq 'HASH' ? %{$_[0]} : @_ }, $class);
13   $NO_BUILD{$class} = !$class->can('BUILD') unless exists $NO_BUILD{$class};
14   $NO_BUILD{$class}
15     ? bless({ ref($_[0]) eq 'HASH' ? %{$_[0]} : @_ }, $class)
16     : do {
17         my $proto = ref($_[0]) eq 'HASH' ? $_[0] : { @_ };
18         bless({ %$proto }, $class)->BUILDALL($proto);
19       };
20 }
21
22 # Inlined into Method::Generate::Constructor::_generate_args() - keep in sync
23 sub BUILDARGS {
24     my $class = shift;
25     if ( scalar @_ == 1 ) {
26         unless ( defined $_[0] && ref $_[0] eq 'HASH' ) {
27             die "Single parameters to new() must be a HASH ref"
28                 ." data => ". $_[0] ."\n";
29         }
30         return { %{ $_[0] } };
31     }
32     elsif ( @_ % 2 ) {
33         die "The new() method for $class expects a hash reference or a key/value list."
34                 . " You passed an odd number of arguments\n";
35     }
36     else {
37         return {@_};
38     }
39 }
40
41 sub BUILDALL {
42   my $self = shift;
43   $self->${\(($BUILD_MAKER ||= do {
44     require Method::Generate::BuildAll;
45     Method::Generate::BuildAll->new
46   })->generate_method(ref($self)))}(@_);
47 }
48
49 sub DESTROY {
50     my $self = shift;
51
52     return unless $self->can('DEMOLISH'); # short circuit
53
54     require Moo::_Utils;
55
56     my $e = do {
57         local $?;
58         local $@;
59         eval {
60             # DEMOLISHALL
61
62             $self->DEMOLISHALL($Moo::_Utils::_in_global_destruction);
63         };
64         $@;
65     };
66
67     no warnings 'misc';
68     die $e if $e; # rethrow
69 }
70
71 sub DEMOLISHALL {
72   my $self = shift;
73   $self->${\(($DEMOLISH_MAKER ||= do {
74     require Method::Generate::DemolishAll;
75     Method::Generate::DemolishAll->new
76   })->generate_method(ref($self)))}(@_);
77 }
78
79 sub does {
80   require Role::Tiny;
81   { no warnings 'redefine'; *does = \&Role::Tiny::does_role }
82   goto &Role::Tiny::does_role;
83 }
84
85 1;