File Coverage

blib/lib/Acme/Mitey/Cards/Mite.pm
Criterion Covered Total %
statement 142 214 66.3
branch 17 58 29.3
condition 1 19 5.2
subroutine 46 57 80.7
pod 0 25 0.0
total 206 373 55.2


line stmt bran cond sub pod time code
1             # NOTE: Since the intention is to ship this file with a project, this file
2             # cannot have any non-core dependencies.
3             package Acme::Mitey::Cards::Mite;
4 9     9   179 use 5.008001;
  9         25  
5 9     9   43 use strict;
  9         13  
  9         165  
6 9     9   43 use warnings;
  9         16  
  9         253  
7 9     9   35 no strict 'refs';
  9         16  
  9         2408  
8              
9             if ( $] < 5.009005 ) { require MRO::Compat; }
10             else { require mro; }
11              
12             defined ${^GLOBAL_PHASE}
13             or eval { require Devel::GlobalDestruction; 1 }
14             or do {
15             carp( "WARNING: Devel::GlobalDestruction recommended!" );
16             *Devel::GlobalDestruction::in_global_destruction = sub { undef; };
17             };
18              
19             # Constants
20             sub true () { !!1 }
21             sub false () { !!0 }
22             sub ro () { 'ro' }
23             sub rw () { 'rw' }
24             sub rwp () { 'rwp' }
25             sub lazy () { 'lazy' }
26             sub bare () { 'bare' }
27              
28             # More complicated constants
29             BEGIN {
30 9     9   44 my @bool = ( \&false, \&true );
31 9         14 *_HAS_AUTOCLEAN = $bool[ 0+!! eval { require namespace::autoclean } ];
  9         1104  
32 9   0     15906 *STRICT = $bool[ 0+!! ( $ENV{PERL_STRICT} || $ENV{EXTENDED_TESTING} || $ENV{AUTHOR_TESTING} || $ENV{RELEASE_TESTING} ) ];
33             };
34              
35             # Exportable error handlers
36             sub _error_handler {
37 4     4   12 my ( $func, $message, @args ) = @_;
38 4 100       11 if ( @args ) {
39 3         1479 require Data::Dumper;
40 3         16689 local $Data::Dumper::Terse = 1;
41 3         7 local $Data::Dumper::Indent = 0;
42             $message = sprintf $message, map {
43 3 50       8 ref($_) ? Data::Dumper::Dumper($_) : defined($_) ? $_ : '(undef)'
  6 50       32  
44             } @args;
45             }
46 4         7 my $next = do { require Carp; \&{"Carp::$func"} };
  4         18  
  4         8  
  4         14  
47 4         11 @_ = ( $message );
48 4         641 goto $next;
49             }
50              
51 1     1 0 2 sub carp { unshift @_, 'carp' ; goto \&_error_handler }
  1         3  
52 3     3 0 11 sub croak { unshift @_, 'croak' ; goto \&_error_handler }
  3         11  
53 0     0 0 0 sub confess { unshift @_, 'confess'; goto \&_error_handler }
  0         0  
54              
55             # Exportable guard function
56             {
57             my $GUARD_PACKAGE = __PACKAGE__ . '::Guard';
58 0 0   0   0 *{"$GUARD_PACKAGE\::DESTROY"} = sub { $_[0][0] or $_[0][1]->() };
59 0     0   0 *{"$GUARD_PACKAGE\::restore"} = sub { $_[0]->DESTROY; $_[0][0] = true };
  0         0  
60 0     0   0 *{"$GUARD_PACKAGE\::dismiss"} = sub { $_[0][0] = true };
61 0     0   0 *{"$GUARD_PACKAGE\::peek"} = sub { $_[0][2] };
62 0     0   0 *guard = sub (&) { bless [ 0, @_ ] => $GUARD_PACKAGE };
63             }
64              
65             sub _is_compiling {
66 31     31   98 return !! $ENV{MITE_COMPILE};
67             }
68              
69             sub import {
70 31     31   62 my $me = shift;
71 31         76 my %arg = map { lc($_) => true } @_;
  31         139  
72 31         109 my ( $caller, $file ) = caller;
73              
74 31 50       66 if( _is_compiling() ) {
75 0         0 require Mite::Project;
76 0         0 Mite::Project->default->inject_mite_functions(
77             package => $caller,
78             file => $file,
79             arg => \%arg,
80             shim => $me,
81             );
82             }
83             else {
84             # Changes to this filename must be coordinated with Mite::Compiled
85 31         66 my $mite_file = $file . ".mite.pm";
86 31 50       493 if( !-e $mite_file ) {
87 0         0 croak "Compiled Mite file ($mite_file) for $file is missing";
88             }
89              
90             {
91 31         70 local @INC = ('.', @INC);
  31         146  
92 31         11307 require $mite_file;
93             }
94             }
95              
96 31         266 warnings->import;
97 31         123 strict->import;
98             'namespace::autoclean'->import( -cleanee => $caller )
99 31         822 if _HAS_AUTOCLEAN && !$arg{'-unclean'};
100             }
101              
102             {
103             my ( $cb_before, $cb_after );
104             sub _finalize_application_roletiny {
105 0     0   0 my ( $me, $role, $caller, $args ) = @_;
106 0 0       0 if ( $INC{'Role/Hooks.pm'} ) {
107 0   0     0 $cb_before ||= \%Role::Hooks::CALLBACKS_BEFORE_APPLY;
108 0   0     0 $cb_after ||= \%Role::Hooks::CALLBACKS_AFTER_APPLY;
109             }
110 0 0       0 if ( $cb_before ) {
111 0 0       0 $_->( $role, $caller ) for @{ $cb_before->{$role} || [] };
  0         0  
112             }
113 0         0 'Role::Tiny'->_check_requires( $caller, $role );
114 0         0 my $info = $Role::Tiny::INFO{$role};
115 0 0       0 for ( @{ $info->{modifiers} || [] } ) {
  0         0  
116 0         0 my @args = @$_;
117 0         0 my $modification = shift @args;
118 0         0 my $handler = "HANDLE_$modification";
119 0         0 $me->$handler( $caller, undef, @args );
120             }
121 0 0       0 if ( $cb_after ) {
122 0 0       0 $_->( $role, $caller ) for @{ $cb_after->{$role} || [] };
  0         0  
123             }
124 0         0 return;
125             }
126              
127             # Usage: $me, $caller, @with_args
128             sub HANDLE_with {
129 0     0 0 0 my ( $me, $caller ) = ( shift, shift );
130 0         0 while ( @_ ) {
131 0         0 my $role = shift;
132 0 0       0 my $args = ref($_[0]) ? shift : undef;
133 0 0 0     0 if ( $INC{'Role/Tiny.pm'} and 'Role::Tiny'->is_role( $role ) ) {
134 0         0 $me->_finalize_application_roletiny( $role, $caller, $args );
135             }
136             else {
137 0         0 $role->__FINALIZE_APPLICATION__( $caller, $args );
138             }
139             }
140 0         0 return;
141             }
142             }
143              
144             # Usage: $me, $caller, $keyword, @has_args
145             sub HANDLE_has {
146 54     54 0 122 my ( $me, $caller, $keyword, $names ) = ( shift, shift, shift, shift );
147 54 50       139 if ( @_ % 2 ) {
148 0         0 my $default = shift;
149 0 0       0 unshift @_, ( 'CODE' eq ref( $default ) )
150             ? ( is => lazy, builder => $default )
151             : ( is => ro, default => $default );
152             }
153 54         154 my %spec = @_;
154 54         75 my $code;
155 54 50       122 for my $name ( ref($names) ? @$names : $names ) {
156 54         88 $name =~ s/^\+//;
157             'CODE' eq ref( $code = $spec{default} )
158 54 50       120 and ${"$caller\::__$name\_DEFAULT__"} = $code;
  0         0  
159             'CODE' eq ref( $code = $spec{builder} )
160 54 100       119 and *{"$caller\::_build_$name"} = $code;
  13         71  
161             'CODE' eq ref( $code = $spec{trigger} )
162 54 50       98 and *{"$caller\::_trigger_$name"} = $code;
  0         0  
163             'CODE' eq ref( $code = $spec{clone} )
164 54 50       118 and *{"$caller\::_clone_$name"} = $code;
  0         0  
165             }
166 54         141 return;
167             }
168              
169             {
170             my $_kind = sub { ${ shift() . '::USES_MITE' } =~ /Role/ ? 'role' : 'class' };
171              
172             sub _get_orig_method {
173 64     64   99 my ( $caller, $name ) = @_;
174 64         347 my $orig = $caller->can( $name );
175 64 50       163 return $orig if $orig;
176 0         0 croak "Cannot modify method $name in $caller: no such method";
177             }
178              
179             sub _parse_mm_args {
180 64     64   85 my $coderef = pop;
181 64 50       127 my $names = [ map { ref($_) ? @$_ : $_ } @_ ];
  64         231  
182 64         154 ( $names, $coderef );
183             }
184              
185             # Usage: $me, $caller, $caller_kind, @before_args
186             sub HANDLE_before {
187 0     0 0 0 my ( $me, $caller, $kind ) = ( shift, shift, shift );
188 0         0 my ( $names, $coderef ) = &_parse_mm_args;
189 0   0     0 $kind ||= $caller->$_kind;
190 0 0       0 if ( $kind eq 'role' ) {
191 0         0 push @{"$caller\::METHOD_MODIFIERS"},
  0         0  
192             [ before => $names, $coderef ];
193 0         0 return;
194             }
195 0         0 for my $name ( @$names ) {
196 0         0 my $orig = _get_orig_method( $caller, $name );
197 0         0 local $@;
198 0 0       0 eval <<"BEFORE" or die $@;
199             package $caller;
200             no warnings 'redefine';
201             sub $name {
202             \$coderef->( \@_ );
203             \$orig->( \@_ );
204             }
205             1;
206             BEFORE
207             }
208 0         0 return;
209             }
210              
211             # Usage: $me, $caller, $caller_kind, @after_args
212             sub HANDLE_after {
213 0     0 0 0 my ( $me, $caller, $kind ) = ( shift, shift, shift );
214 0         0 my ( $names, $coderef ) = &_parse_mm_args;
215 0   0     0 $kind ||= $caller->$_kind;
216 0 0       0 if ( $kind eq 'role' ) {
217 0         0 push @{"$caller\::METHOD_MODIFIERS"},
  0         0  
218             [ after => $names, $coderef ];
219 0         0 return;
220             }
221 0         0 for my $name ( @$names ) {
222 0         0 my $orig = _get_orig_method( $caller, $name );
223 0         0 local $@;
224 0 0       0 eval <<"AFTER" or die $@;
225             package $caller;
226             no warnings 'redefine';
227             sub $name {
228             my \@r;
229             if ( wantarray ) {
230             \@r = \$orig->( \@_ );
231             }
232             elsif ( defined wantarray ) {
233             \@r = scalar \$orig->( \@_ );
234             }
235             else {
236             \$orig->( \@_ );
237             1;
238             }
239             \$coderef->( \@_ );
240             wantarray ? \@r : \$r[0];
241             }
242             1;
243             AFTER
244             }
245 0         0 return;
246             }
247              
248             # Usage: $me, $caller, $caller_kind, @around_args
249             sub HANDLE_around {
250 64     64 0 115 my ( $me, $caller, $kind ) = ( shift, shift, shift );
251 64         105 my ( $names, $coderef ) = &_parse_mm_args;
252 64   33     128 $kind ||= $caller->$_kind;
253 64 50       129 if ( $kind eq 'role' ) {
254 0         0 push @{"$caller\::METHOD_MODIFIERS"},
  0         0  
255             [ around => $names, $coderef ];
256 0         0 return;
257             }
258 64         105 for my $name ( @$names ) {
259 64         114 my $orig = _get_orig_method( $caller, $name );
260 64         88 local $@;
261 9 50   9 0 53 eval <<"AROUND" or die $@;
  9     8 0 15  
  9     7 0 450  
  8     7 0 46  
  8     5 0 14  
  8     4 0 334  
  7     4 0 38  
  7     4 0 13  
  7     2 0 337  
  7     2 0 38  
  7     2 0 13  
  7     2 0 275  
  5     2 0 27  
  5     2 0 8  
  5     2 0 197  
  4     2 0 23  
  4     4   5  
  4     25   156  
  4     2   21  
  4     9   6  
  4     1   144  
  4     38   20  
  4     8   7  
  4     122   146  
  2     4   11  
  2     1   3  
  2     6   78  
  2     122   11  
  2     7   3  
  2     36   94  
  2     2   12  
  2     0   5  
  2         73  
  2         10  
  2         4  
  2         92  
  2         11  
  2         3  
  2         84  
  2         11  
  2         4  
  2         71  
  2         11  
  2         4  
  2         97  
  2         11  
  2         4  
  2         84  
  64         3809  
  4         15  
  25         1460  
  2         31  
  9         1640  
  1         4  
  38         90  
  8         2665  
  122         275  
  4         527  
  1         4  
  6         47  
  122         283  
  7         29  
  36         84  
  2         5  
  0         0  
262             package $caller;
263             no warnings 'redefine';
264             sub $name {
265             \$coderef->( \$orig, \@_ );
266             }
267             1;
268             AROUND
269             }
270 64         150 return;
271             }
272             }
273              
274             # Usage: $me, $caller, $caller_kind, @signature_for_args
275             sub HANDLE_signature_for {
276 64     64 0 137 my ( $me, $caller, $kind, $name ) = @_;
277 64         122 $name =~ s/^\+//;
278 64         97 $me->HANDLE_around( $caller, $kind, $name, ${"$caller\::SIGNATURE_FOR"}{$name} );
  64         271  
279 64         156 return;
280             }
281              
282             1;