File Coverage

blib/lib/Mite/Role.pm
Criterion Covered Total %
statement 64 70 91.4
branch 11 14 78.5
condition 1 2 50.0
subroutine 12 16 75.0
pod 0 3 0.0
total 88 105 83.8


line stmt bran cond sub pod time code
1 15     15   285 use 5.010001;
  15         49  
2 15     15   80 use strict;
  15         38  
  15         314  
3 15     15   65 use warnings;
  15         27  
  15         649  
4              
5             use Mite::Miteception -all;
6 15     15   123 extends qw(
  15         24  
  15         116  
7             Mite::Package
8             );
9             with qw(
10             Mite::Trait::HasRequiredMethods
11             Mite::Trait::HasAttributes
12             Mite::Trait::HasRoles
13             Mite::Trait::HasMethods
14             Mite::Trait::HasMOP
15             );
16              
17             our $AUTHORITY = 'cpan:TOBYINK';
18             our $VERSION = '0.010008';
19              
20             use Path::Tiny;
21 15     15   91 use B ();
  15         34  
  15         690  
22 15     15   74  
  15         29  
  15         12680  
23              
24 20     20 0 52 my ( $self, $role_args ) = @_;
25              
26             my %methods = %{ $self->methods_to_import_from_roles };
27 12     12 0 31 my %native = %{ $self->native_methods };
28             my $package = $self->name;
29 12         36  
  12         48  
30 12         33 for my $name ( keys %native ) {
  12         36  
31 12         41 $methods{$name} = "$package\::$name";
32             }
33 12         34  
34 10         26 if ( my $excludes = $role_args->{'-excludes'} ) {
35             for my $excluded ( ref( $excludes ) ? @$excludes : $excludes ) {
36             delete $methods{$excluded};
37 12 100       45 }
38 1 50       5 }
39 1         3  
40             if ( my $alias = $role_args->{'-alias'} ) {
41             for my $oldname ( sort keys %$alias ) {
42             my $newname = $alias->{$oldname};
43 12 100       45 $methods{$newname} = delete $methods{$oldname};
44 1         3 }
45 1         2 }
46 1         2  
47             return \%methods;
48             }
49              
50 12         53 my $self = shift;
51             return {} unless $self->arg->{'-runtime'};
52              
53             my @accessors = map $_->associated_methods,
54 1     1 0 3 sort { $a->_order <=> $b->_order }
55 1 50       5 values %{ $self->attributes };
56              
57             return { map { $_ => $self->name . "::$_"; } @accessors };
58 0         0 }
59 1         2  
  1         24  
60             around compilation_stages => sub {
61 1         2 my ( $next, $self ) = ( shift, shift );
  4         16  
62             my @stages = $self->$next( @_ );
63             push @stages, qw(
64             _compile_callback
65             );
66             push @stages, '_compile_runtime_application'
67             if $self->arg->{'-runtime'};
68             return @stages;
69             };
70              
71             my $self = shift;
72             my $name = $self->name;
73              
74             my $methods = {
75             %{ $self->methods_to_export },
76 1     1   2 %{ $self->accessors_to_export },
77 1         4 };
78             my $method_hash = join qq{,\n},
79             map sprintf(
80 1         5 ' %s => %s',
81 1         1 B::perlstring( $_ ),
  1         3  
82             B::perlstring( $methods->{$_} =~ /^\Q$name\E::(\w+)$/ ? $1 : $methods->{$_} )
83             ),
84             sort keys %$methods;
85              
86             return sprintf <<'CODE', $method_hash;
87 1 50       69 {
88             our ( %%METHODS ) = (
89             %s
90             );
91 1         31  
92             my %%DONE;
93             sub APPLY_TO {
94             my $to = shift;
95             if ( ref $to ) {
96             my $new_class = CREATE_CLASS( ref $to );
97             return bless( $to, $new_class );
98             }
99             return if $DONE{$to};
100             {
101             no strict 'refs';
102             ${"$to\::USES_MITE"} = 'Mite::Class';
103             for my $method ( keys %%METHODS ) {
104             $to->can($method) or *{"$to\::$method"} = \&{ $METHODS{$method} };
105             }
106             for ( "DOES", "does" ) {
107             $to->can( $_ ) or *{"$to\::$_"} = sub { shift->isa( @_ ) };
108             }
109             }
110             __PACKAGE__->__FINALIZE_APPLICATION__( $to );
111             $MITE_SHIM->HANDLE_around( $to, "class", [ "DOES", "does" ], sub {
112             my ( $next, $self, $role ) = @_;
113             return 1 if $role eq __PACKAGE__;
114             return 1 if $role eq $to;
115             return $self->$next( $role );
116             } );
117             $DONE{$to}++;
118             return;
119             }
120              
121             sub CREATE_CLASS {
122             my $base = shift;
123             my $new_class = "$base\::__WITH__::" . __PACKAGE__;
124             {
125             no strict 'refs';
126             @{"$new_class\::ISA"} = $base;
127             }
128             APPLY_TO( $new_class );
129             return $new_class;
130             }
131             }
132             CODE
133             }
134              
135             my $self = shift;
136              
137             my @required = @{ $self->required_methods };
138             my %uniq; undef $uniq{$_} for @required;
139             @required = sort keys %uniq;
140              
141 10     10   29 my $role_list = join q[, ], map B::perlstring( $_->name ), @{ $self->roles };
142             my $shim = B::perlstring(
143 10         17 $self->shim_name
  10         50  
144 10         22 || eval { $self->project->config->data->{shim} }
  10         27  
145 10         74 || 'Mite::Shim'
146             );
147 10         30 my $croak = $self->_function_for_croak;
  10         40  
148             my $missing_methods = '()';
149             if ( @required ) {
150 10   50     37 require B;
151             $missing_methods = sprintf 'grep( !$target->can($_), %s )',
152             join q[, ], map B::perlstring( $_ ), @required;
153 10         54 }
154 10         26  
155 10 100       68 return sprintf <<'CODE', $missing_methods, $croak, $role_list, $croak, $shim;
156 2         11 # Callback which classes consuming this role will call
157 2         16 sub __FINALIZE_APPLICATION__ {
158             my ( $me, $target, $args ) = @_;
159             our ( %%CONSUMERS, @METHOD_MODIFIERS );
160              
161 10         241 # Ensure a given target only consumes this role once.
162             if ( exists $CONSUMERS{$target} ) {
163             return;
164             }
165             $CONSUMERS{$target} = 1;
166              
167             my $type = do { no strict 'refs'; ${"$target\::USES_MITE"} };
168             return if $type ne 'Mite::Class';
169              
170             my @missing_methods;
171             @missing_methods = %s
172             and %s( "$me requires $target to implement methods: " . join q[, ], @missing_methods );
173              
174             my @roles = ( %s );
175             my %%nextargs = %%{ $args || {} };
176             ( $nextargs{-indirect} ||= 0 )++;
177             %s( "PANIC!" ) if $nextargs{-indirect} > 100;
178             for my $role ( @roles ) {
179             $role->__FINALIZE_APPLICATION__( $target, { %%nextargs } );
180             }
181              
182             my $shim = %s;
183             for my $modifier_rule ( @METHOD_MODIFIERS ) {
184             my ( $modification, $names, $coderef ) = @$modifier_rule;
185             my $handler = "HANDLE_$modification";
186             $shim->$handler( $target, "class", $names, $coderef );
187             }
188              
189             return;
190             }
191             CODE
192             }
193              
194             my $self = shift;
195             $self->arg->{'-runtime'} ? true : false;
196             }
197              
198             return '$META_ROLE';
199             }
200              
201 10     10   15 return 'Moose::Meta::Role::Attribute';
202 10 100       111 }
203              
204             my $self = shift;
205              
206 0     0     return sprintf <<'CODE', $self->name;
207             for ( @%s::METHOD_MODIFIERS ) {
208             my ( $type, $names, $code ) = @$_;
209             $PACKAGE->${\"add_$type\_method_modifier"}( $_, $code ) for @$names;
210 0     0     }
211             CODE
212             }
213              
214 0     0     return sprintf ' Moose::Util::TypeConstraints::find_or_create_does_type_constraint( %s );',
215             B::perlstring( shift->name );
216 0           }
217              
218             1;