File Coverage

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


line stmt bran cond sub pod time code
1             package MooX::ValidateSubs;
2              
3 9     9   744781 use strict;
  9         48  
  9         271  
4 9     9   51 use warnings;
  9         17  
  9         218  
5              
6 9     9   4134 use MooX::ReturnModifiers;
  9         4889  
  9         434  
7 9     9   61 use B;
  9         16  
  9         5189  
8             our $VERSION = '1.012005';
9              
10             sub import {
11 18     18   8694 my $target = caller;
12 18         89 my %modifiers = return_modifiers($target, [qw/has with around/]);
13            
14             my $raise_context_error = sub {
15 15     15   43 my ($error, $c) = @_;
16 15 100       50 if (ref $error) {
17 10         78 my $gv = B::svref_2object($c)->GV;
18 10         57 $error->{context}->{file} = $gv->FILE;
19 10         42 $error->{context}->{line} = $gv->LINE;
20             }
21 15         81 die $error;
22 18         705 };
23              
24             my $validate_subs = sub {
25 13     13   25281 my @attr = @_;
26 13         62 while (@attr) {
27 20 100       2237 my @names = ref $attr[0] eq 'ARRAY' ? @{ shift @attr } : shift @attr;
  4         13  
28 20         42 my $spec = shift @attr;
29 20         52 for my $name (@names) {
30 24         5633 my $store_spec = sprintf '%s_spec', $name;
31 24     26   196 $modifiers{has}->( $store_spec => ( is => 'ro', default => sub { $spec } ) );
  26         35378  
32 24 100       53101 unless ( $name =~ m/^\+/ ) {
33             $modifiers{around}->(
34             $name,
35             sub {
36 48     48   28917 my ( $orig, $self, @params ) = @_;
37 48         180 my @caller = caller;
38            
39 48 50       153 if (! ref $self) {
40 0         0 $self = $self->new;
41             }
42            
43 48         208 my $current_spec = $self->$store_spec;
44              
45 48 100       144 if ( my $param_spec = $current_spec->{params} ) {
46 39         72 @params = eval { $self->_validate_sub(
  39         150  
47             $name, 'params', $param_spec, @params
48             ) };
49 39 100       1449 if ($@) {
50 11         86 $raise_context_error->($@, $orig);
51             }
52             }
53              
54 37 100       109 if (my $keys = $current_spec->{keys}) {
55 3 100       11 my $hash = scalar @params > 1 ? { @params } : $params[0];
56 3         5 @params = map { $hash->{$_} } @{ $keys };
  9         21  
  3         7  
57             }
58              
59 37         137 @params = $self->$orig(@params);
60              
61 37 100       366 if ( my $param_spec = $current_spec->{returns} ) {
62 14         27 @params = eval { $self->_validate_sub(
  14         47  
63             $name, 'returns', $param_spec, @params
64             ) };
65 14 100       453 if ($@) {
66 4         33 $raise_context_error->($@, $orig);
67             }
68             }
69              
70 33 100       185 return wantarray ? @params : shift @params;
71             }
72 23         179 );
73             }
74             }
75             }
76 18         106 };
77              
78 18 50       180 $target->can('_validate_sub') or $modifiers{with}->('MooX::ValidateSubs::Role');
79              
80             {
81 9     9   74 no strict 'refs';
  9         18  
  9         695  
  18         148171  
82 18         42 *{"${target}::validate_subs"} = $validate_subs;
  18         108  
83             }
84              
85 18         637 return 1;
86             }
87              
88             1;
89              
90             __END__