File Coverage

lib/Attribute/Context.pm
Criterion Covered Total %
statement 39 76 51.3
branch 0 32 0.0
condition n/a
subroutine 15 20 75.0
pod 5 5 100.0
total 59 133 44.3


line stmt bran cond sub pod time code
1             package Attribute::Context;
2              
3 5     5   183968 use strict;
  5         13  
  5         185  
4              
5 5     5   33 no warnings 'redefine';
  5         9  
  5         166  
6 5     5   5777 use Attribute::Handlers;
  5         33355  
  5         33  
7 5     5   215 use vars qw($VERSION);
  5         12  
  5         527  
8             $VERSION = '0.042';
9              
10             my $_setup = sub {
11             my ( $package, $symbol, $referent, $attr, $data, $phase ) = @_;
12              
13             my $subroutine;
14             {
15 5     5   26 no strict 'refs';
  5         11  
  5         2153  
16             $subroutine = $package . '::' . *{$symbol}{NAME};
17             }
18             if ( 'ARRAY' eq ref $data ) {
19             if ( @$data % 2 ) {
20             die
21             "$attr arguments to $subroutine must be a single argument or an even sized list";
22             }
23             my %hash = @$data;
24             $data = \%hash;
25             }
26             elsif ( 'Custom' eq $attr ) {
27             $data = { class => $data };
28             }
29             else {
30             $data = $data ? { $data => 1 } : {};
31             }
32             return $package, $subroutine, $symbol, $referent, $data;
33             };
34              
35             my $_hash_branch_exists;
36             $_hash_branch_exists = sub {
37             my ( $hash, $branch ) = @_;
38             return 1 unless @$branch; # we got to the end of the branch successfully
39             my $key = shift @$branch;
40             return unless exists $hash->{$key};
41             return $_hash_branch_exists->( $hash->{$key}, $branch );
42             };
43              
44             my $_void_handler = sub {
45             my ( $subroutine, $data ) = @_;
46             if ( $data->{NOVOID} ) {
47             die "You may not call $subroutine() in void context";
48             }
49             elsif ( $data->{WARNVOID} ) {
50             warn "Useless use of $subroutine() in void context";
51             }
52             return;
53             };
54              
55             sub Arrayref : ATTR(CODE) {
56 2     2 1 8740 my ( $package, $subroutine, $symbol, $referent, $data ) = $_setup->(@_);
57              
58             *$symbol = sub {
59 0     0   0 local *__ANON__ = '__ANON__Arrayref_wrapper';
60 0         0 my @results = $referent->(@_);
61 0 0       0 return $_void_handler->( $subroutine, $data )
62             unless defined wantarray;
63 0 0       0 return wantarray ? @results : \@results;
64 1         10 };
65 5     5   38 }
  5         8  
  5         26  
66              
67             sub Last : ATTR(CODE) {
68 2     2 1 6389 my ( $package, $subroutine, $symbol, $referent, $data ) = $_setup->(@_);
69              
70             *$symbol = sub {
71 0     0   0 local *__ANON__ = '__ANON__Last_wrapper';
72 0         0 my @results = $referent->(@_);
73 0 0       0 return $_void_handler->( $subroutine, $data )
74             unless defined wantarray;
75 0 0       0 if (wantarray) {
    0          
76 0         0 return @results;
77             }
78             elsif (@results) {
79 0         0 return $results[-1];
80             }
81             else {
82 0         0 return;
83             }
84 1         9 };
85 5     5   2512 }
  5         9  
  5         36  
86              
87             sub First : ATTR(CODE) {
88 2     2 1 8057 my ( $package, $subroutine, $symbol, $referent, $data ) = $_setup->(@_);
89              
90             *$symbol = sub {
91 0     0   0 local *__ANON__ = '__ANON__First_wrapper';
92 0         0 my @results = $referent->(@_);
93 0 0       0 return $_void_handler->( $subroutine, $data )
94             unless defined wantarray;
95 0 0       0 if (wantarray) {
    0          
96 0         0 return @results;
97             }
98             elsif (@results) {
99 0         0 return $results[0];
100             }
101             else {
102 0         0 return;
103             }
104 1         8 };
105 5     5   2546 }
  5         10  
  5         39  
106              
107             sub Count : ATTR(CODE) {
108 2     2 1 6111 my ( $package, $subroutine, $symbol, $referent, $data ) = $_setup->(@_);
109              
110             *$symbol = sub {
111 0     0   0 local *__ANON__ = '__ANON__Count_wrapper';
112 0         0 my @results = $referent->(@_);
113 0 0       0 return $_void_handler->( $subroutine, $data )
114             unless defined wantarray;
115 0 0       0 return wantarray ? @results : scalar @results;
116 1         8 };
117 5     5   1986 }
  5         12  
  5         22  
118              
119             sub Custom : ATTR(CODE) {
120 1     1 1 6307 my ( $package, $subroutine, $symbol, $referent, $data ) = $_setup->(@_);
121 0           my $class = $data->{class};
122 0 0         unless ($class) {
123 0           die "No class specified for $subroutine Custom attribute";
124             }
125              
126             # we walk the symbol table because a package declaration in another package
127             # won't necessarily be reflected in %INC
128 0           my $sym_table_package = "${class}::";
129 0           my @keys = split /(?<=::)/, $sym_table_package;
130 0 0         unless ( $_hash_branch_exists->( \%::, \@keys ) ) {
131 0           eval "use $class";
132 0 0         die $@ if $@;
133             }
134 0 0         unless ( $class->can('new') ) {
135 0           die "Cannot find constructor 'new' for $class";
136             }
137              
138             *$symbol = sub {
139 0     0     local *__ANON__ = '__ANON__Count_wrapper';
140 0           my @results = $referent->(@_);
141 0 0         return $_void_handler->( $subroutine, $data )
142             unless defined wantarray;
143 0 0         return wantarray ? @results : $class->new( \@results );
144 0           };
145 5     5   3935 }
  5         12  
  5         27  
146              
147             1;
148              
149             __END__