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   861957 use v5.14.0;
  5         37  
3 5     5   25 use strict;
  5         8  
  5         109  
4 5     5   26 use warnings;
  5         20  
  5         269  
5              
6             our $VERSION = "0.02";
7              
8 5     5   2830 use Attribute::Handlers;
  5         22794  
  5         28  
9 5     5   2695 use B::Hooks::EndOfScope;
  5         55282  
  5         39  
10 5     5   2615 use Sub::WrapInType ();
  5         847691  
  5         182  
11 5     5   43 use Sub::Util ();
  5         13  
  5         89  
12 5     5   27 use attributes;
  5         11  
  5         42  
13 5     5   276 use namespace::autoclean;
  5         11  
  5         64  
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   35 my $class = shift;
21 5         14 my %args = @_;
22              
23 5 100       20 my $pkg = $args{pkg} ? $args{pkg} : scalar caller;
24 5 100       27 $CHECK{$pkg} = !!$args{check} if exists $args{check};
25             {
26             # allow importing package to use attribute
27 5     5   768 no strict qw(refs);
  5         11  
  5         1199  
  5         9  
28 5         56 my $MODIFY_CODE_ATTRIBUTES = \&Attribute::Handlers::UNIVERSAL::MODIFY_CODE_ATTRIBUTES;
29 5         11 *{"${pkg}::MODIFY_CODE_ATTRIBUTES"} = $MODIFY_CODE_ATTRIBUTES;
  5         35  
30 5         23 *{"${pkg}::_ATTR_CODE_WrapSub"} = $class->can('WrapSub');
  5         22  
31 5         19 *{"${pkg}::_ATTR_CODE_WrapMethod"} = $class->can('WrapMethod');
  5         45  
32             }
33              
34             on_scope_end {
35 5     5   960 while (my $args = shift @INSTALL_ARGS) {
36 10         51 $class->_install(@$args);
37             }
38 5         43 };
39 5         270 return;
40             }
41              
42             sub WrapSub :ATTR(CODE,BEGIN) {
43 6     6 1 24794 my ($pkg, @args) = @_;
44              
45             my $opts = {
46 6   100     51 check => $CHECK{$pkg} // $DEFAULT_CHECK,
47             skip_invocant => 0,
48             };
49 6         59 push @INSTALL_ARGS => [$opts, $pkg, @args];
50 6         19 return;
51 5     5   39 }
  5         11  
  5         24  
52              
53             sub WrapMethod :ATTR(CODE,BEGIN) {
54 4     4 1 10254 my ($pkg, @args) = @_;
55              
56             my $opts = {
57 4   100     36 check => $CHECK{$pkg} // $DEFAULT_CHECK,
58             skip_invocant => 1,
59             };
60 4         15 push @INSTALL_ARGS => [$opts, $pkg, @args];
61 4         14 return;
62 5     5   2276 }
  5         19  
  5         28  
63              
64             sub _install {
65 10     10   22 my $class = shift;
66 10         37 my ($options, $pkg, $symbol, $code, $attr, $data) = @_;
67              
68 10         63 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       95085 if (my @attr = attributes::get($code)) {
76 5     5   1697 no warnings qw(misc);
  5         34  
  5         454  
77 1         31 attributes->import($pkg, $typed_code, @attr);
78             }
79              
80 10         340 my $prototype = Sub::Util::prototype($code);
81 10         71 Sub::Util::set_prototype($prototype, $typed_code);
82 10         103 Sub::Util::set_subname(Sub::Util::subname($code), $typed_code);
83              
84             {
85 5     5   33 no strict qw(refs);
  5         12  
  5         183  
  10         18  
86 5     5   36 no warnings qw(redefine);
  5         10  
  5         527  
87 10         36 *$symbol = $typed_code;
88             }
89 10         83 return;
90             }
91              
92             1;
93             __END__