File Coverage

blib/lib/Sub/WrapInType/Attribute.pm
Criterion Covered Total %
statement 79 79 100.0
branch 6 6 100.0
condition 6 6 100.0
subroutine 20 20 100.0
pod 2 2 100.0
total 113 113 100.0


line stmt bran cond sub pod time code
1             package Sub::WrapInType::Attribute;
2 5     5   778389 use v5.14.0;
  5         36  
3 5     5   25 use strict;
  5         8  
  5         97  
4 5     5   22 use warnings;
  5         16  
  5         229  
5              
6             our $VERSION = "0.01";
7              
8 5     5   2503 use Attribute::Handlers;
  5         19692  
  5         27  
9 5     5   2494 use B::Hooks::EndOfScope;
  5         48658  
  5         35  
10 5     5   2388 use Sub::WrapInType ();
  5         771505  
  5         154  
11 5     5   41 use Sub::Util ();
  5         12  
  5         74  
12 5     5   24 use attributes;
  5         10  
  5         41  
13 5     5   257 use namespace::autoclean;
  5         10  
  5         47  
14              
15             my $DEFAULT_CHECK = !!($ENV{SUB_WRAPINTYPE_ATTRIBUTE_CHECK} // 1);
16             my %CHECK;
17             my @INSTALL_ARGS;
18              
19             sub import {
20 5     5   33 my $class = shift;
21 5         12 my %args = @_;
22              
23 5 100       18 my $pkg = $args{pkg} ? $args{pkg} : scalar caller;
24 5 100       21 $CHECK{$pkg} = !!$args{check} if exists $args{check};
25             {
26             # allow importing package to use attribute
27 5     5   629 no strict qw(refs);
  5         10  
  5         1061  
  5         9  
28 5         57 my $MODIFY_CODE_ATTRIBUTES = \&Attribute::Handlers::UNIVERSAL::MODIFY_CODE_ATTRIBUTES;
29 5         8 *{"${pkg}::MODIFY_CODE_ATTRIBUTES"} = $MODIFY_CODE_ATTRIBUTES;
  5         31  
30 5         21 *{"${pkg}::_ATTR_CODE_WrapSub"} = $class->can('WrapSub');
  5         20  
31 5         16 *{"${pkg}::_ATTR_CODE_WrapMethod"} = $class->can('WrapMethod');
  5         33  
32             }
33              
34             on_scope_end {
35 5     5   782 while (my $args = shift @INSTALL_ARGS) {
36 10         51 $class->_install(@$args);
37             }
38 5         38 };
39 5         220 return;
40             }
41              
42             sub WrapSub :ATTR(CODE,BEGIN) {
43 6     6 1 15829 my ($pkg, @args) = @_;
44              
45             my $opts = {
46 6   100     50 check => $CHECK{$pkg} // $DEFAULT_CHECK,
47             skip_invocant => 0,
48             };
49 6         54 push @INSTALL_ARGS => [$opts, $pkg, @args];
50 6         20 return;
51 5     5   38 }
  5         10  
  5         22  
52              
53             sub WrapMethod :ATTR(CODE,BEGIN) {
54 4     4 1 4347 my ($pkg, @args) = @_;
55              
56             my $opts = {
57 4   100     27 check => $CHECK{$pkg} // $DEFAULT_CHECK,
58             skip_invocant => 1,
59             };
60 4         15 push @INSTALL_ARGS => [$opts, $pkg, @args];
61 4         10 return;
62 5     5   2015 }
  5         17  
  5         32  
63              
64             sub _install {
65 10     10   23 my $class = shift;
66 10         31 my ($options, $pkg, $symbol, $code, $attr, $data) = @_;
67              
68 10         58 my $typed_code = Sub::WrapInType->new(
69             params => $data->[0],
70             isa => $data->[1],
71             code => $code,
72             options => $options,
73             );
74              
75 10 100       85437 if (my @attr = attributes::get($code)) {
76 5     5   1475 no warnings qw(misc);
  5         28  
  5         380  
77 1         33 attributes->import($pkg, $typed_code, @attr);
78             }
79              
80 10         318 my $prototype = Sub::Util::prototype($code);
81 10         69 Sub::Util::set_prototype($prototype, $typed_code);
82 10         92 Sub::Util::set_subname(Sub::Util::subname($code), $typed_code);
83              
84             {
85 5     5   32 no strict qw(refs);
  5         10  
  5         153  
  10         17  
86 5     5   24 no warnings qw(redefine);
  5         10  
  5         430  
87 10         32 *$symbol = $typed_code;
88             }
89 10         82 return;
90             }
91              
92             1;
93             __END__