File Coverage

blib/lib/MooX/ValidateSubs.pm
Criterion Covered Total %
statement 61 61 100.0
branch 21 22 95.4
condition n/a
subroutine 10 10 100.0
pod n/a
total 92 93 98.9


line stmt bran cond sub pod time code
1             package MooX::ValidateSubs;
2              
3 9     9   728317 use strict;
  9         45  
  9         256  
4 9     9   47 use warnings;
  9         15  
  9         211  
5              
6 9     9   3975 use MooX::ReturnModifiers;
  9         4522  
  9         446  
7 9     9   64 use B;
  9         27  
  9         4818  
8             our $VERSION = '1.012004';
9              
10             sub import {
11 18     18   8916 my $target = caller;
12 18         72 my %modifiers = return_modifiers($target);
13            
14             my $raise_context_error = sub {
15 15     15   40 my ($error, $c) = @_;
16 15 100       67 if (ref $error) {
17 10         91 my $gv = B::svref_2object($c)->GV;
18 10         60 $error->{context}->{file} = $gv->FILE;
19 10         45 $error->{context}->{line} = $gv->LINE;
20             }
21 15         80 die $error;
22 18         875 };
23              
24             my $validate_subs = sub {
25 13     13   25635 my @attr = @_;
26 13         61 while (@attr) {
27 20 100       2227 my @names = ref $attr[0] eq 'ARRAY' ? @{ shift @attr } : shift @attr;
  4         16  
28 20         44 my $spec = shift @attr;
29 20         48 for my $name (@names) {
30 24         5624 my $store_spec = sprintf '%s_spec', $name;
31 24     26   188 $modifiers{has}->( $store_spec => ( is => 'ro', default => sub { $spec } ) );
  26         34803  
32 24 100       51440 unless ( $name =~ m/^\+/ ) {
33             $modifiers{around}->(
34             $name,
35             sub {
36 48     48   29207 my ( $orig, $self, @params ) = @_;
37 48         170 my @caller = caller;
38            
39 48         179 my $current_spec = $self->$store_spec;
40              
41 48 100       166 if ( my $param_spec = $current_spec->{params} ) {
42 39         81 @params = eval { $self->_validate_sub(
  39         161  
43             $name, 'params', $param_spec, @params
44             ) };
45 39 100       1379 if ($@) {
46 11         119 $raise_context_error->($@, $orig);
47             }
48             }
49              
50 37 100       129 if (my $keys = $current_spec->{keys}) {
51 3 100       12 my $hash = scalar @params > 1 ? { @params } : $params[0];
52 3         12 @params = map { $hash->{$_} } @{ $keys };
  9         23  
  3         6  
53             }
54              
55 37         139 @params = $self->$orig(@params);
56              
57 37 100       345 if ( my $param_spec = $current_spec->{returns} ) {
58 14         22 @params = eval { $self->_validate_sub(
  14         49  
59             $name, 'returns', $param_spec, @params
60             ) };
61 14 100       406 if ($@) {
62 4         20 $raise_context_error->($@, $orig);
63             }
64             }
65              
66 33 100       230 return wantarray ? @params : shift @params;
67             }
68 23         196 );
69             }
70             }
71             }
72 18         96 };
73              
74 18 50       171 $target->can('_validate_sub') or $modifiers{with}->('MooX::ValidateSubs::Role');
75              
76             {
77 9     9   74 no strict 'refs';
  9         16  
  9         751  
  18         146843  
78 18         43 *{"${target}::validate_subs"} = $validate_subs;
  18         103  
79             }
80              
81 18         647 return 1;
82             }
83              
84             1;
85              
86             __END__