File Coverage

blib/lib/Devel/StackTrace/WithLexicals.pm
Criterion Covered Total %
statement 68 87 78.1
branch 13 28 46.4
condition n/a
subroutine 13 13 100.0
pod n/a
total 94 128 73.4


line stmt bran cond sub pod time code
1             package Devel::StackTrace::WithLexicals;
2 7     7   199607 use strict;
  7         232  
  7         293  
3 7     7   41 use warnings;
  7         17  
  7         233  
4 7     7   197 use 5.008001;
  7         30  
  7         318  
5 7     7   39 use base 'Devel::StackTrace';
  7         15  
  7         12383  
6              
7 7     7   52916 use Devel::StackTrace::WithLexicals::Frame;
  7         21  
  7         284  
8              
9 7     7   8114 use PadWalker 'peek_my';
  7         8258  
  7         13860  
10              
11             our $VERSION = '0.10';
12              
13             sub _record_caller_data {
14 9     9   18726 my $self = shift;
15              
16 9         83 $self->SUPER::_record_caller_data(@_);
17              
18 9         1293 my $caller = -1;
19 9         19 my $walker = 0;
20              
21 9         81 while (my (undef, undef, undef, $sub) = caller(++$caller)) {
22             # PadWalker ignores eval block and eval string, we must do so too
23 27 100       111 next if $sub eq '(eval)';
24              
25 25         216 $self->{raw}[$caller]{lexicals} = peek_my(++$walker);
26 25 100       172 if ($self->{no_refs}) {
27 4         6 for (values %{ $self->{raw}[$caller]{lexicals} }) {
  4         22  
28 12 100       122 $_ = $$_ if ref($_) eq 'REF';
29 12         31 $_ = $self->_ref_to_string($_);
30             }
31             }
32             }
33              
34             # don't want to include the frame for this method!
35 9         27 shift @{ $self->{raw} };
  9         34  
36             }
37              
38             # this is a reimplementation of code already in Devel::StackTrace
39             # but it's too hairy to make it subclassable because of backcompat
40             # so I copied and pasted it and made it.. modern
41             sub _ignore_package_list {
42 9     9   16 my $self = shift;
43              
44 9         17 my @i_pack_re;
45              
46 9 50       39 if ($self->{ignore_package}) {
47 0 0       0 $self->{ignore_package} = [ $self->{ignore_package} ]
48             unless ref($self->{ignore_package}) eq 'ARRAY';
49              
50 0 0       0 @i_pack_re = map { ref $_ ? $_ : qr/^\Q$_\E$/ }
  0         0  
51 0         0 @{ $self->{ignore_package} };
52             }
53              
54 9         41 push @i_pack_re, qr/^Devel::StackTrace$/;
55              
56 9         18 my $p = __PACKAGE__;
57 9         150 push @i_pack_re, qr/^\Q$p\E$/;
58              
59 9         37 return @i_pack_re;
60             }
61              
62             sub _ignore_class_map {
63 9     9   17 my $self = shift;
64              
65 9 50       36 if ($self->{ignore_class}) {
66 0 0       0 $self->{ignore_class} = [ $self->{ignore_class} ]
67             unless ref($self->{ignore_class}) eq 'ARRAY';
68              
69 0         0 return map { $_ => 1 } @{ $self->{ignore_class} };
  0         0  
  0         0  
70             }
71              
72 9         39 return ();
73             }
74              
75             sub _normalize_args {
76 18     18   26 my $self = shift;
77 18         25 my $args = shift;
78              
79 18 100       47 if ($self->{no_refs}) {
80 2         5 for (grep { ref } @$args) {
  6         13  
81             # I can't remember what this is about but I think
82             # it must be to avoid a loop between between
83             # Exception::Class and this module.
84 0 0       0 if (UNIVERSAL::isa($_, 'Exception::Class::Base')) {
85 0         0 $_ = do {
86 0 0       0 if ($_->can('show_trace')) {
87 0         0 my $t = $_->show_trace;
88 0         0 $_->show_trace(0);
89 0         0 my $s = "$_";
90 0         0 $_->show_trace($t);
91 0         0 $s;
92             }
93             else {
94             # hack but should work with older
95             # versions of E::C::B
96 0         0 $_->{message};
97             }
98             };
99             }
100             else {
101 0         0 $_ = $self->_ref_to_string($_);
102             }
103             }
104             }
105              
106 18         54 return $args;
107             }
108              
109 18     18   194 sub _frame_class { "Devel::StackTrace::WithLexicals::Frame" }
110              
111             sub _make_frames {
112 9     9   229 my $self = shift;
113              
114 9         35 my @i_pack_re = $self->_ignore_package_list;
115 9         38 my %i_class = $self->_ignore_class_map;
116              
117 9         17 for my $r (@{ $self->{raw} }) {
  9         30  
118 18 50       55 next if grep { $r->{caller}[0] =~ /$_/ } @i_pack_re;
  36         253  
119 18 50       51 next if grep { $r->{caller}[0]->isa($_) } keys %i_class;
  0         0  
120              
121 18         54 $self->_add_frame($r);
122             }
123              
124             # if we don't delete this key then D:ST will call _make_frames again
125 9         85 delete $self->{raw};
126             }
127              
128             sub _add_frame {
129 18     18   25 my $self = shift;
130 18         29 my $frame_data = shift;
131              
132 18         62 my $c = $frame_data->{caller};
133 18         28 my $args = $frame_data->{args};
134              
135             # eval and is_require are only returned when applicable under 5.00503.
136 18 50       48 push @$c, (undef, undef)
137             if scalar @$c == 6;
138              
139 18         54 $frame_data->{args} = $self->_normalize_args($frame_data->{args});
140              
141 18         46 my $frame = $self->_frame_class->new(
142             %$frame_data,
143             message => $self->{message},
144             indent => $self->{indent},
145             respect_overload => $self->{respect_overload},
146             max_arg_length => $self->{max_arg_length},
147             );
148              
149 18         52 push @{ $self->{frames} }, $frame;
  18         65  
150             }
151              
152              
153             1;
154              
155             __END__