File Coverage

blib/lib/MooX/ValidateSubs.pm
Criterion Covered Total %
statement 58 58 100.0
branch 24 24 100.0
condition n/a
subroutine 9 9 100.0
pod n/a
total 91 91 100.0


line stmt bran cond sub pod time code
1             package MooX::ValidateSubs;
2              
3 10     10   1211251 use strict;
  10         21  
  10         374  
4 10     10   45 use warnings;
  10         20  
  10         540  
5              
6 10     10   5233 use MooX::ReturnModifiers;
  10         7848  
  10         653  
7 10     10   70 use B;
  10         366  
  10         7352  
8             our $VERSION = '1.012010';
9              
10             sub import {
11 19     19   22056 my $target = caller;
12 19         92 my %modifiers = return_modifiers($target, [qw/has with around sub/]);
13            
14             my $raise_context_error = sub {
15 19     19   71 my ($error, $c) = @_;
16 19 100       103 if (ref $error) {
17 12         162 my $gv = B::svref_2object($c)->GV;
18 12         109 $error->{context}->{file} = $gv->FILE . '::' . $gv->NAME;
19 12         178 $error->{context}->{line} = $gv->LINE;
20             }
21 19         134 die $error;
22 19         900 };
23              
24             my $validate_subs = sub {
25 14     14   1496303 my @attr = @_;
26 14         56 while (@attr) {
27 27 100       5251 my @names = ref $attr[0] eq 'ARRAY' ? @{ shift @attr } : shift @attr;
  6         20  
28 27         59 my $spec = shift @attr;
29 27         98 for my $name (@names) {
30 33         9188 my $store_spec = sprintf '%s_spec', $name;
31 33     36   307 $modifiers{has}->( $store_spec => ( is => 'ro', default => sub { $spec } ) );
  36         696416  
32 33 100       66744 unless ( $name =~ m/^\+/ ) {
33             $modifiers{around}->(
34             $name,
35             sub {
36 70     70   63562 my ( $orig, $self, @params ) = @_;
37 70         354 my @caller = caller;
38            
39 70 100       295 if (! ref $self) {
40 1         31 $self = $self->new;
41             }
42            
43 70         334 my $current_spec = $self->$store_spec;
44              
45 70 100       304 if ( my $param_spec = $current_spec->{params} ) {
46 61         132 @params = eval { $self->_validate_sub(
  61         287  
47             $name, 'params', $param_spec, @params
48             ) };
49 61 100       1859 if ($@) {
50 15         157 $raise_context_error->($@, $orig);
51             }
52             }
53              
54 55 100       203 if (my $keys = $current_spec->{keys}) {
55 6 100       25 my $hash = scalar @params > 1 ? { @params } : $params[0];
56 6         12 @params = map { $hash->{$_} } @{ $keys };
  18         55  
  6         18  
57             }
58              
59 55         216 @params = $self->$orig(@params);
60              
61 55 100       548 if ( my $param_spec = $current_spec->{returns} ) {
62 15         26 @params = eval { $self->_validate_sub(
  15         57  
63             $name, 'returns', $param_spec, @params
64             ) };
65 15 100       507 if ($@) {
66 4         19 $raise_context_error->($@, $orig);
67             }
68             }
69              
70 51 100       428 return wantarray ? @params : shift @params;
71             }
72 32         268 );
73             }
74             }
75             }
76 19         120 };
77              
78 19 100       199 $target->can('_validate_sub') or $modifiers{with}->('MooX::ValidateSubs::Role');
79            
80 19         198980 $modifiers{sub}->('validate_subs', $validate_subs);
81              
82 19         939 return 1;
83             }
84              
85             1;
86              
87             __END__