factor out and rename
[gitmo/Moo.git] / lib / Moo.pm
1 package Moo;
2
3 use strictures 1;
4 use Moo::_Utils;
5
6 our %MAKERS;
7
8 sub import {
9   my $target = caller;
10   my $class = shift;
11   strictures->import;
12   *{_getglob("${target}::extends")} = sub {
13     *{_getglob("${target}::ISA")} = \@_;
14   };
15   *{_getglob("${target}::with")} = sub {
16     require Moo::Role;
17     die "Only one role supported at a time by with" if @_ > 1;
18     Moo::Role->apply_role_to_package($_[0], $target);
19   };
20   $MAKERS{$target} = {};
21   *{_getglob("${target}::has")} = sub {
22     my ($name, %spec) = @_;
23     ($MAKERS{$target}{accessor} ||= do {
24       require Method::Generate::Accessor;
25       Method::Generate::Accessor->new
26     })->generate_method($target, $name, \%spec);
27     $class->_constructor_maker_for($target)
28           ->register_attribute_specs($name, \%spec);
29   };
30   foreach my $type (qw(before after around)) {
31     *{_getglob "${target}::${type}"} = sub {
32       _install_modifier($target, $type, @_);
33     };
34   }
35   {
36     no strict 'refs';
37     @{"${target}::ISA"} = do {
38       require Moo::Object; ('Moo::Object');
39     } unless @{"${target}::ISA"};
40   }
41 }
42
43 sub _constructor_maker_for {
44   my ($class, $target) = @_;
45   return unless $MAKERS{$target};
46   $MAKERS{$target}{constructor} ||= do {
47     require Method::Generate::Constructor;
48     Method::Generate::Constructor
49       ->new(
50         package => $target,
51         accessor_generator => do {
52           require Method::Generate::Accessor;
53           Method::Generate::Accessor->new;
54         }
55       )
56       ->install_delayed
57       ->register_attribute_specs(do {
58         my @spec;
59         # using the -last- entry in @ISA means that classes created by
60         # Role::Tiny as N roles + superclass will still get the attributes
61         # from the superclass
62         if (my $super = do { no strict 'refs'; ${"${target}::ISA"}[-1] }) {
63           if (my $con = $MAKERS{$super}{constructor}) {
64             @spec = %{$con->all_attribute_specs};
65           }
66         }
67         @spec;
68       });
69   }
70 }
71
72 1;