File Coverage

blib/lib/Sub/Talisman.pm
Criterion Covered Total %
statement 95 98 96.9
branch 7 12 58.3
condition n/a
subroutine 27 28 96.4
pod 4 4 100.0
total 133 142 93.6


line stmt bran cond sub pod time code
1             package Sub::Talisman;
2              
3 1     1   30458 use 5.008;
  1         4  
  1         37  
4 1     1   6 use strict;
  1         1  
  1         30  
5 1     1   5 use warnings;
  1         6  
  1         50  
6              
7             BEGIN {
8 1     1   8 $Sub::Talisman::AUTHORITY = 'cpan:TOBYINK';
9 1         16 $Sub::Talisman::VERSION = '0.004';
10             }
11              
12 1     1   1827 use Attribute::Handlers;
  1         3440  
  1         6  
13 1     1   1301 use Sub::Identify qw( get_code_info );
  1         1328  
  1         71  
14 1     1   991 use Sub::Name qw( subname );
  1         599  
  1         64  
15 1     1   2248 use Scalar::Does qw( does -constants );
  1         156807  
  1         16  
16 1     1   2546 use Scalar::Util qw( refaddr );
  1         2  
  1         238  
17              
18             sub _identify
19             {
20             my $sub = shift;
21             if (does $sub, CODE)
22             {
23             my ($p, $n) = get_code_info($sub);
24             $n .= sprintf('(%d)', refaddr($sub)) if $n eq '__ANON__';
25             return ($p, $n);
26             }
27             elsif ($sub =~ /::/)
28             {
29             my ($p, $n) = ($sub =~ /^(.*)::(\w+)$/);
30             $p = 'main' if $p eq q();
31             return ($p, $n);
32             }
33             else
34             {
35             return ($_[0], $sub);
36             }
37             }
38              
39 1     1   6 use namespace::clean;
  1         3  
  1         5  
40             my (%TALI, %FETCH);
41              
42             sub setup_for
43             {
44 4     4 1 7 my ($class, $caller, $opts) = @_;
45 4         23 my $atr = $opts->{attribute};
46 1     1   7 eval qq{
  1     1   1  
  1     1   8  
  0     1   0  
  0     0   0  
  0     3   0  
  1     2   5  
  1     2   2  
  1         4  
  3         2847  
  3         17  
  3         10  
  1         5  
  1         2  
  1         4  
  2         107  
  2         12  
  2         6  
  1         6  
  1         2  
  1         4  
  2         104  
  2         10  
  2         6  
  4         482  
47             package $caller;
48             sub $atr :ATTR(CODE)
49             {
50             unshift \@_, q[$class], q[$caller];
51             my \$callback = "$class"->can("_callback");
52             goto \$callback;
53             }
54             };
55 4         892 namespace::clean->import(
56             -cleanee => $caller,
57             $opts->{attribute},
58             );
59 4 100       182 unless ($FETCH{$caller})
60             {
61 1     1   480 no strict 'refs';
  1         2  
  1         794  
62 1         3 my $subname = "$caller\::FETCH_CODE_ATTRIBUTES";
63             *$subname = subname $subname, sub {
64 1     1   499 my ($class, $sub) = @_;
        1      
65 1 50       4 return map { /(\w+)$/ ? $1 : () }
  3         28  
66             __PACKAGE__->get_attributes($sub);
67 1         14 };
68 1         40 $FETCH{$caller} = 1;
69             }
70             }
71              
72             sub import
73             {
74 1     1   8 my $class = shift;
75 1         3 my $caller = caller;
76 1         2 foreach my $atr (@_)
77             {
78 4         16 $class->setup_for($caller, { attribute => $atr });
79             }
80             }
81              
82             sub _process_params
83             {
84 7     7   11 my ($class, $attr, $params) = @_;
85 7         15 return $params;
86             }
87              
88             sub _callback
89             {
90 7     7   19 my ($class, $installation_pkg, $caller_pkg, $glob, $ref, $attr, $params, $step, $file, $line) = @_;
91 7         22 my ($p, $n) = _identify($ref, scalar caller);
92 7         22 my $full_attr = join q[::], $installation_pkg, $attr;
93 7         23 my $obj = $class->_process_params($full_attr, $params);
94 7         43 $TALI{$p}{$n}{$full_attr} = $obj;
95             }
96              
97             sub get_attributes
98             {
99 4     4 1 1306 my ($class, $sub) = @_;
100 4         14 my ($p, $n) = _identify($sub, scalar caller);
101 4 50       9 my %hash = %{ $TALI{$p}{$n} || {} };
  4         32  
102 4         27 return sort keys %hash;
103             }
104              
105             sub get_attribute_parameters
106             {
107 3     3 1 430 my ($class, $sub, $attr) = @_;
108 3 50       12 $attr = scalar(caller).'::'.$attr unless $attr =~ /::/;
109 3         7 my ($p, $n) = _identify($sub, scalar caller);
110 3 50       14 return unless exists $TALI{$p}{$n}{$attr};
111 3         16 return $TALI{$p}{$n}{$attr};
112             }
113              
114             sub get_subs
115             {
116 3     3 1 2150 my ($class, $attr) = @_;
117 3 50       11 $attr = scalar(caller).'::'.$attr unless $attr =~ /::/;
118 3         3 my @subs;
119 3         9 foreach my $pkg (keys %TALI)
120             {
121 7         19 push @subs,
122 9         16 map { "$pkg\::$_" }
123 9         12 grep { exists $TALI{$pkg}{$_}{$attr} }
124 3         6 grep { not /^__ANON__\([0-9]+\)$/ }
125 3         4 keys %{ $TALI{$pkg} };
126             }
127 3         14 return @subs;
128             }
129              
130             1;
131              
132             __END__