File Coverage

blib/lib/Hook/LexWrap.pm
Criterion Covered Total %
statement 83 85 97.6
branch 46 48 95.8
condition 16 17 94.1
subroutine 19 21 90.4
pod 1 1 100.0
total 165 172 95.9


line stmt bran cond sub pod time code
1             package Hook::LexWrap;
2 2     2   43453 use 5.006;
  2         8  
  2         79  
3 2     2   12 use strict;
  2         3  
  2         77  
4 2     2   11 use warnings;
  2         9  
  2         107  
5             our $VERSION = '0.24';
6 2     2   12 use Carp;
  2         4  
  2         306  
7            
8             {
9 2     2   10 no warnings 'redefine';
  2         4  
  2         431  
10             *CORE::GLOBAL::caller = sub (;$) {
11 86   100 86   323 my ($height) = ($_[0]||0);
12 86         96 my $i=1;
13 86         83 my $name_cache;
14 86         90 while (1) {
15 402 100       2440 my @caller = CORE::caller($i++) or return;
16 390 100       1057 $caller[3] = $name_cache if $name_cache;
17 390 100       669 $name_cache = $caller[0] eq 'Hook::LexWrap' ? $caller[3] : '';
18 390 100 100     1742 next if $name_cache || $height-- != 0;
19 74 100       1060 return wantarray ? @_ ? @caller : @caller[0..2] : $caller[0];
    100          
20             }
21             };
22             }
23            
24 2     2   15 sub import { no strict 'refs'; *{caller()."::wrap"} = \&wrap }
  2     2   3  
  2         855  
  2         18  
  2         377  
25            
26             sub wrap (*@) { ## no critic Prototypes
27 28     28 1 366 my ($typeglob, %wrapper) = @_;
28 28 100 100     169 $typeglob = (ref $typeglob || $typeglob =~ /::/)
29             ? $typeglob
30             : caller()."::$typeglob";
31 28         34 my $original;
32             {
33 2     2   12 no strict 'refs';
  2         3  
  2         245  
  28         32  
34 28   66     235 $original = ref $typeglob eq 'CODE' && $typeglob
35             || *$typeglob{CODE}
36             || croak "Can't wrap non-existent subroutine ", $typeglob;
37             }
38 54 100       283 croak "'$_' value is not a subroutine reference"
39 27         40 foreach grep {$wrapper{$_} && ref $wrapper{$_} ne 'CODE'}
40             qw(pre post);
41 2     2   11 no warnings 'redefine';
  2         6  
  2         754  
42 25         50 my ($caller, $unwrap) = *CORE::GLOBAL::caller{CODE};
43             my $imposter = sub {
44 52 100   52   197 if ($unwrap) { goto &$original }
  24         34  
45 28         30 my ($return, $prereturn);
46 28 100       66 if (wantarray) {
    100          
47 11         19 $prereturn = $return = [];
48 11 100       41 () = $wrapper{pre}->(@_,$return) if $wrapper{pre};
49 11 100 100     135 if (ref $return eq 'ARRAY' && $return == $prereturn && !@$return) {
      100        
50 7         14 $return = [ &$original ];
51 7 100       72 () = $wrapper{post}->(@_, $return)
52             if $wrapper{post};
53             }
54 11 100       97 return ref $return eq 'ARRAY' ? @$return : ($return);
55             }
56             elsif (defined wantarray) {
57 4     4   26 $return = bless sub {$prereturn=1}, 'Hook::LexWrap::Cleanup';
  4         25  
58 4 100       17 my $dummy = $wrapper{pre}->(@_, $return) if $wrapper{pre};
59 4 100       24 unless ($prereturn) {
60 3         7 $return = &$original;
61 3 50       15 $dummy = scalar $wrapper{post}->(@_, $return)
62             if $wrapper{post};
63             }
64 4         25 return $return;
65             }
66             else {
67 13     13   61 $return = bless sub {$prereturn=1}, 'Hook::LexWrap::Cleanup';
  13         45  
68 13 100       58 $wrapper{pre}->(@_, $return) if $wrapper{pre};
69 13 50       60 unless ($prereturn) {
70 13         32 &$original;
71 13 100       108 $wrapper{post}->(@_, $return)
72             if $wrapper{post};
73             }
74 13         66 return;
75             }
76 25         145 };
77 25 100       79 ref $typeglob eq 'CODE' and return defined wantarray
    100          
78             ? $imposter
79             : carp "Uselessly wrapped subroutine reference in void context";
80             {
81 2     2   10 no strict 'refs';
  2         4  
  2         356  
  23         31  
82 23         25 *{$typeglob} = $imposter;
  23         76  
83             }
84 23 100       74 return unless defined wantarray;
85 10     10   81 return bless sub{ $unwrap=1 }, 'Hook::LexWrap::Cleanup';
  10         34  
86             }
87            
88             package Hook::LexWrap::Cleanup;
89            
90 27     27   693 sub DESTROY { $_[0]->() }
91             use overload
92 6     6   120 q{""} => sub { undef },
93 0     0   0 q{0+} => sub { undef },
94 0     0   0 q{bool} => sub { undef },
95 2     2   3966 q{fallback}=>1; #fallback=1 - like no overloading for other operations
  2         3571  
  2         31  
96            
97             1;
98            
99             __END__