Commit | Line | Data |
3362e41c |
1 | package Moo::HandleMoose; |
2 | |
3 | use strictures 1; |
4 | use Moo::_Utils; |
5 | |
6 | sub import { inject_all() } |
7 | |
8 | sub inject_all { |
9 | require Class::MOP; |
10 | inject_fake_metaclass_for($_) for grep $_ ne 'Moo::Object', keys %Moo::MAKERS; |
11 | } |
12 | |
13 | sub inject_fake_metaclass_for { |
14 | my ($name) = @_; |
15 | require Class::MOP; |
16 | Class::MOP::store_metaclass_by_name( |
17 | $name, bless({ name => $name }, 'Moo::HandleMoose::FakeMetaClass') |
18 | ); |
19 | } |
20 | |
21 | our %DID_INJECT; |
22 | |
23 | sub inject_real_metaclass_for { |
24 | my ($name) = @_; |
25 | return Class::MOP::get_metaclass_by_name($name) if $DID_INJECT{$name}; |
26 | require Moose; require Moo; require Moo::Role; |
27 | Class::MOP::remove_metaclass_by_name($name); |
28 | my ($meta, $attr_specs) = do { |
29 | if (my $info = $Moo::Role::INFO{$name}) { |
30 | (Moose::Meta::Role->initialize($name), $info->{attributes}) |
31 | } else { |
32 | my $specs = Moo->_constructor_maker_for($name)->all_attribute_specs; |
33 | (Moose::Meta::Class->initialize($name), $specs); |
34 | } |
35 | }; |
36 | my %methods = %{Role::Tiny->_concrete_methods_of($name)}; |
37 | my @attrs; |
38 | { |
39 | local @{_getstash($name)}{keys %methods}; |
40 | foreach my $name (keys %$attr_specs) { |
41 | push @attrs, $meta->add_attribute($name => %{$attr_specs->{$name}}); |
42 | } |
43 | } |
44 | foreach my $attr (@attrs) { |
45 | foreach my $method (@{$attr->associated_methods}) { |
46 | $method->{body} = $name->can($method->name); |
47 | } |
48 | } |
49 | $DID_INJECT{$name} = 1; |
50 | $meta; |
51 | } |
52 | |
53 | { |
54 | package Moo::HandleMoose::FakeMetaClass; |
55 | |
56 | sub DESTROY { } |
57 | |
58 | sub AUTOLOAD { |
59 | my ($meth) = (our $AUTOLOAD =~ /([^:]+)$/); |
60 | Moo::HandleMoose::inject_real_metaclass_for((shift)->{name})->$meth(@_) |
61 | } |
62 | sub can { |
63 | Moo::HandleMoose::inject_real_metaclass_for((shift)->{name})->can(@_) |
64 | } |
65 | sub isa { |
66 | Moo::HandleMoose::inject_real_metaclass_for((shift)->{name})->isa(@_) |
67 | } |
68 | } |
69 | |
70 | 1; |