File Coverage

blib/lib/MooX/ValidateSubs.pm
Criterion Covered Total %
statement 63 63 100.0
branch 24 24 100.0
condition n/a
subroutine 10 10 100.0
pod n/a
total 97 97 100.0


line stmt bran cond sub pod time code
1             package MooX::ValidateSubs;
2              
3 10     10   638694 use strict;
  10         42  
  10         246  
4 10     10   47 use warnings;
  10         16  
  10         214  
5              
6 10     10   3650 use MooX::ReturnModifiers;
  10         4236  
  10         409  
7 10     10   57 use B;
  10         19  
  10         4680  
8             our $VERSION = '1.012006';
9              
10             sub import {
11 19     19   8184 my $target = caller;
12 19         88 my %modifiers = return_modifiers($target, [qw/has with around/]);
13            
14             my $raise_context_error = sub {
15 19     19   47 my ($error, $c) = @_;
16 19 100       62 if (ref $error) {
17 12         112 my $gv = B::svref_2object($c)->GV;
18 12         66 $error->{context}->{file} = $gv->FILE;
19 12         62 $error->{context}->{line} = $gv->LINE;
20             }
21 19         96 die $error;
22 19         600 };
23              
24             my $validate_subs = sub {
25 14     14   25535 my @attr = @_;
26 14         58 while (@attr) {
27 27 100       3587 my @names = ref $attr[0] eq 'ARRAY' ? @{ shift @attr } : shift @attr;
  6         22  
28 27         51 my $spec = shift @attr;
29 27         56 for my $name (@names) {
30 33         7227 my $store_spec = sprintf '%s_spec', $name;
31 33     36   213 $modifiers{has}->( $store_spec => ( is => 'ro', default => sub { $spec } ) );
  36         38364  
32 33 100       51733 unless ( $name =~ m/^\+/ ) {
33             $modifiers{around}->(
34             $name,
35             sub {
36 70     70   40486 my ( $orig, $self, @params ) = @_;
37 70         215 my @caller = caller;
38            
39 70 100       203 if (! ref $self) {
40 1         23 $self = $self->new;
41             }
42            
43 70         260 my $current_spec = $self->$store_spec;
44              
45 70 100       201 if ( my $param_spec = $current_spec->{params} ) {
46 61         95 @params = eval { $self->_validate_sub(
  61         236  
47             $name, 'params', $param_spec, @params
48             ) };
49 61 100       1629 if ($@) {
50 15         96 $raise_context_error->($@, $orig);
51             }
52             }
53              
54 55 100       140 if (my $keys = $current_spec->{keys}) {
55 6 100       20 my $hash = scalar @params > 1 ? { @params } : $params[0];
56 6         11 @params = map { $hash->{$_} } @{ $keys };
  18         40  
  6         13  
57             }
58              
59 55         174 @params = $self->$orig(@params);
60              
61 55 100       438 if ( my $param_spec = $current_spec->{returns} ) {
62 15         28 @params = eval { $self->_validate_sub(
  15         41  
63             $name, 'returns', $param_spec, @params
64             ) };
65 15 100       319 if ($@) {
66 4         18 $raise_context_error->($@, $orig);
67             }
68             }
69              
70 51 100       266 return wantarray ? @params : shift @params;
71             }
72 32         212 );
73             }
74             }
75             }
76 19         104 };
77              
78 19 100       164 $target->can('_validate_sub') or $modifiers{with}->('MooX::ValidateSubs::Role');
79              
80             {
81 10     10   68 no strict 'refs';
  10         18  
  10         717  
  19         124947  
82 19         47 *{"${target}::validate_subs"} = $validate_subs;
  19         93  
83             }
84              
85 19         594 return 1;
86             }
87              
88             1;
89              
90             __END__