File Coverage

blib/lib/Devel/CallerStack.pm
Criterion Covered Total %
statement 99 101 98.0
branch 20 24 83.3
condition 4 5 80.0
subroutine 28 28 100.0
pod 20 20 100.0
total 171 178 96.0


line stmt bran cond sub pod time code
1             package Devel::CallerStack;
2 1     1   5059 use strict;
  1         3  
  1         33  
3 1     1   4 use warnings;
  1         1  
  1         29  
4              
5 1     1   5 use Devel::CallerStack::Level;
  1         2  
  1         29  
6 1     1   5 use base 'Exporter';
  1         1  
  1         114  
7 1     1   10 use Carp;
  1         1  
  1         1022  
8              
9             our $VERSION = '0.003';
10             our @EXPORT_OK = qw/ caller_stack /;
11              
12 1     1 1 27 sub caller_stack { __PACKAGE__->new( 4 )}
13              
14             sub new {
15 2     2 1 5 my $class = shift;
16 2         4 my ( $depth ) = @_;
17 2         9 my $self = bless( [[], undef, 0], $class );
18 2   100     20 $self->_build($depth || 3);
19 2         8 return $self;
20             }
21              
22             sub _build {
23 2     2   4 my $self = shift;
24 2         4 my ($depth) = @_;
25 2         15 while ( my $level = Devel::CallerStack::Level->new( $depth++ )) {
26 9 50       26 next if $level->package->isa( __PACKAGE__ );
27 9         15 push @{ $self->all } => $level;
  9         18  
28             }
29 2         4 return $self;
30             }
31              
32 31     31   75 sub _index { \shift->[2] }
33 2     2 1 9 sub index { ${ shift->_index }}
  2         5  
34              
35 57     57 1 455 sub all { shift->[0] }
36 1     1 1 5 sub all_list { @{ shift->all }}
  1         3  
37              
38             sub _filtered {
39 66     66   100 my $self = shift;
40 66 100       164 ($self->[1]) = @_ if @_;
41 66         277 return $self->[1];
42             }
43             sub filtered {
44 53     53 1 66 my $self = shift;
45 53   66     126 return $self->_filtered( @_ ) || $self->all;
46             }
47 7     7 1 11 sub filtered_list { @{ shift->filtered }}
  7         22  
48 10 100   10 1 428 sub is_filtered { shift->_filtered ? 1 : 0 }
49              
50             sub unfilter {
51 3     3 1 6 my $self = shift;
52 3         8 $self->_filtered( undef );
53 3         6 return $self;
54             }
55              
56             sub element {
57 1     1 1 3 my $self = shift;
58 1         3 my ( $i ) = @_;
59 1         3 return $self->filtered->[$i];
60             }
61              
62             sub recent_package_caller {
63 1     1 1 19 my $self = shift;
64 1         2 my ( $package ) = @_;
65 1 50       4 croak "You must specify a package name" unless $package;
66 1         2 for my $level ( @{ $self->filtered }) {
  1         3  
67 2 100       7 return $level if $level->package( $package );
68             }
69 0         0 return undef;
70             }
71              
72             sub distant_package_caller {
73 1     1 1 2 my $self = shift;
74 1         2 my ( $package ) = @_;
75 1 50       5 croak "You must specify a package name" unless $package;
76 1         3 for my $level ( reverse @{ $self->filtered }) {
  1         3  
77 2 100       6 return $level if $level->package( $package );
78             }
79 0         0 return undef;
80             }
81              
82             sub package_callers {
83 1     1 1 2 my $self = shift;
84 1         4 my ( $package ) = @_;
85 1 50       4 croak "You must specify a package name" unless $package;
86              
87 1         2 my @out;
88 1         3 for my $level ( @{ $self->filtered }) {
  1         3  
89 4 100       12 push @out => $level if $level->package( $package );
90             }
91              
92 1         22 return @out;
93             }
94              
95             sub filter {
96 4     4 1 11 my $self = shift;
97 4         10 $self->reset;
98 4         9 my ( $attr, $check ) = @_;
99 4         5 my @list = grep { $_->$attr( $check )} @{ $self->filtered };
  20         69  
  4         10  
100              
101 4         16 my $want = wantarray;
102              
103 4 100       17 return @list if $want;
104              
105 3         9 $self->filtered( \@list );
106              
107 3         8 return $self;
108             }
109              
110             sub attribute_stack {
111 1     1 1 3 my $self = shift;
112 1         3 my ( $attribute ) = @_;
113 1         2 return [ map { $_->$attribute } @{ $self->filtered }];
  5         15  
  1         4  
114             }
115              
116             sub recent {
117 1     1 1 3 my $self = shift;
118 1         5 return $self->filtered->[0];
119             }
120              
121             sub distant {
122 1     1 1 1 my $self = shift;
123 1         2 return $self->filtered->[-1];
124             }
125              
126             sub next {
127 17     17 1 41 my $self = shift;
128 17         37 my $idx = $self->_index;
129 17 100       24 return if $$idx >= @{ $self->filtered };
  17         30  
130 10         17 return $self->filtered->[$$idx++];
131             }
132              
133             sub previous {
134 7     7 1 15 my $self = shift;
135 7         14 my $idx = $self->_index;
136 7 100       21 return if $$idx < 1;
137 5         10 return $self->filtered->[--$$idx];
138             }
139              
140             sub reset {
141 5     5 1 6 my $self = shift;
142 5         9 ${ $self->_index } = 0;
  5         12  
143             }
144              
145             1;
146              
147             __END__