File Coverage

blib/lib/MouseX/AttributeTraitHelper/Merge.pm
Criterion Covered Total %
statement 9 9 100.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 12 12 100.0


line stmt bran cond sub pod time code
1             package MouseX::AttributeTraitHelper::Merge;
2 1     1   27246 use Mouse::Role;
  1         1  
  1         7  
3 1     1   216 use Mouse::Util;
  1         2  
  1         4  
4              
5             has TRAIT_MAPPING => (
6             is => 'ro',
7             isa => 'HashRef[ClassName]',
8             default => sub {return {}},
9             );
10              
11             around add_attribute => sub {
12             my ($orig, $self) = (shift, shift);
13              
14             return $self->$orig($_[0]) if Scalar::Util::blessed($_[0]);
15              
16             my $name = shift;
17             my $args = (@_ == 1) ? $_[0] : +{ @_ };
18              
19             defined($name)
20             or $self->throw_error('You must provide a name for the attribute');
21              
22             my $traits = delete $args->{traits};
23             if ($traits) {
24             my $role_name;
25             if (@$traits == 1) {
26             $role_name = $traits->[0];
27             }
28             else {
29             $role_name = join "::" , 'MouseX::AttributeTraitHelper::Merge' , @$traits;
30             $self->TRAIT_MAPPING->{$_} = $role_name for @$traits;
31             if (!Mouse::Util::is_class_loaded($role_name)) {
32             my $meta = Mouse::Role->init_meta(for_class => $role_name);
33             $meta->add_around_method_modifier('does' => sub {
34             my ($orig_meta, $self_meta, $role) = @_;
35             if ($self->TRAIT_MAPPING->{$role}){
36             return 1;
37             }
38             else {
39             return $self_meta->$orig_meta($role)
40             }
41             });
42             my @trait_clones_meta = ();
43             for my $trait (@$traits) {
44             Mouse::Util::load_class($trait);
45             my $trait_clone = join "::" , 'MouseX::AttributeTraitHelper::Merge::CLONE', $trait;
46             if(!Mouse::Util::is_class_loaded($trait_clone)) {
47             my $trait_clone_meta = Mouse::Role->init_meta(for_class => $trait_clone);
48             $trait->meta->apply($trait_clone_meta);
49             for my $trait_attr_name ($trait->meta->get_attribute_list()) {
50             $trait_clone_meta->remove_attribute($trait_attr_name);
51             }
52             }
53             push @trait_clones_meta, $trait_clone->meta;
54             }
55             Mouse::Util::apply_all_roles($meta, @trait_clones_meta);
56             for my $trait (@$traits) {
57             for my $trait_attr_name ($trait->meta->get_attribute_list()) {
58             my $trait_attr = $trait->meta->get_attribute($trait_attr_name);
59             $trait_attr_name =~ s/^\+//;
60             my $exist_trait_attr = $meta->get_attribute($trait_attr_name);
61             if ($exist_trait_attr) {
62             @$exist_trait_attr{keys %$trait_attr} = values %$trait_attr;
63             }
64             else {
65             $meta->add_attribute($trait_attr_name => (is => 'ro', %$trait_attr));
66             }
67             }
68             }
69             }
70             }
71             $args->{traits} = [$role_name];
72             }
73             return $self->$orig($name, @_ == 1 ? $args : %$args);
74             };
75              
76 1     1   534 no Mouse::Role;
  1         2  
  1         4  
77             1;
78             __END__