File Coverage

lib/Aspect/Hook/LexWrap.pm
Criterion Covered Total %
statement 51 67 76.1
branch 21 48 43.7
condition 5 17 29.4
subroutine 12 16 75.0
pod 0 1 0.0
total 89 149 59.7


line stmt bran cond sub pod time code
1             package Aspect::Hook::LexWrap;
2              
3             our $VERSION = '0.20';
4 1     1   32 use 5.006;
  1         5  
  1         53  
5 1     1   755 use Carp::Heavy; # added by eilara as hack around caller() core dump
  1         161  
  1         42  
6 1     1   7 use Carp;
  1         2  
  1         456  
7              
8             *CORE::GLOBAL::caller = sub {
9 32   50 32   6903 my ($height) = ($_[0]||0);
10 32         34 my $i=1;
11 32         25 my $name_cache;
12 32         33 while (1) {
13 96 50       635 my @caller = CORE::caller($i++) or return;
14 96 50       202 $caller[3] = $name_cache if $name_cache;
15 96 50       179 $name_cache = $caller[0] eq 'Aspect::Hook::LexWrap' ? $caller[3] : '';
16 96 100 66     450 next if $name_cache || $height-- != 0;
17 32 0       1038 return wantarray ? @_ ? @caller : @caller[0..2] : $caller[0];
    50          
18             }
19             };
20              
21 1     1   15 sub import { *{caller()."::wrap"} = \&wrap }
  1         41  
22              
23             sub wrap (*@) {
24 9     9 0 40 my ($typeglob, %wrapper) = @_;
25 9 50 33     94 $typeglob = (ref $typeglob || $typeglob =~ /::/)
26             ? $typeglob
27             : caller()."::$typeglob";
28 9   33     131 my $original = ref $typeglob eq 'CODE' && $typeglob
29             || *$typeglob{CODE}
30             || croak "Can't wrap non-existent subroutine ", $typeglob;
31 18 100       105 croak "'$_' value is not a subroutine reference"
32 9         24 foreach grep {$wrapper{$_} && ref $wrapper{$_} ne 'CODE'}
33             qw(pre post);
34 1     1   8 no warnings 'redefine';
  1         1  
  1         818  
35 9         28 my ($caller, $unwrap) = *CORE::GLOBAL::caller{CODE};
36             $imposter = sub {
37 46 100   46   2466 if ($unwrap) { goto &$original }
  32         76  
38 14         18 my ($return, $prereturn);
39 14 50       39 if (wantarray) {
    50          
40 0         0 $prereturn = $return = [];
41 0 0       0 () = $wrapper{pre}->(\@_, $original, $return) if $wrapper{pre};
42 0 0 0     0 if (ref $return eq 'ARRAY' && $return == $prereturn && !@$return) {
      0        
43 0         0 $return = [ &$original(@_) ];
44 0 0       0 () = $wrapper{post}->(\@_, $original, $return)
45             if $wrapper{post};
46             }
47 0 0       0 return ref $return eq 'ARRAY' ? @$return : ($return);
48             }
49             elsif (defined wantarray) {
50 14     14   273 $return = bless sub {$prereturn=1}, 'Aspect::Hook::LexWrap::Cleanup';
  14         79  
51 14 100       71 my $dummy = $wrapper{pre}->(\@_, $original, $return) if $wrapper{pre};
52 14 100       38 unless ($prereturn) {
53 9         25 $return = &$original(@_);
54 9 100       45 $dummy = scalar $wrapper{post}->(\@_, $original, $return)
55             if $wrapper{post};
56             }
57 14         61 return $return;
58             }
59             else {
60 0     0   0 $return = bless sub {$prereturn=1}, 'Aspect::Hook::LexWrap::Cleanup';
  0         0  
61 0 0       0 $wrapper{pre}->(\@_, $original, $return) if $wrapper{pre};
62 0 0       0 unless ($prereturn) {
63 0         0 &$original(@_);
64 0 0       0 $wrapper{post}->(\@_, $original, $return)
65             if $wrapper{post};
66             }
67 0         0 return;
68             }
69 9         82 };
70 9 0       26 ref $typeglob eq 'CODE' and return defined wantarray
    50          
71             ? $imposter
72             : carp "Uselessly wrapped subroutine reference in void context";
73 9         15 *{$typeglob} = $imposter;
  9         39  
74 9 50       34 return unless defined wantarray;
75 9     9   105 return bless sub{ $unwrap=1 }, 'Aspect::Hook::LexWrap::Cleanup';
  9         47  
76             }
77              
78             package Aspect::Hook::LexWrap::Cleanup;
79              
80 23     23   4286 sub DESTROY { $_[0]->() }
81             use overload
82 0     0   0 q{""} => sub { undef },
83 0     0   0 q{0+} => sub { undef },
84 1     1   7 q{bool} => sub { undef };
  1     0   2  
  1         21  
  0         0  
85              
86             1;
87              
88             __END__