File Coverage

blib/lib/Devel/StackTrace/Frame.pm
Criterion Covered Total %
statement 59 67 88.0
branch 20 28 71.4
condition 6 9 66.6
subroutine 8 8 100.0
pod 2 3 66.6
total 95 115 82.6


line stmt bran cond sub pod time code
1             package Devel::StackTrace::Frame;
2              
3 10     10   62 use strict;
  10         18  
  10         251  
4 10     10   49 use warnings;
  10         17  
  10         443  
5              
6             our $VERSION = '2.03';
7              
8             # Create accessor routines
9             BEGIN {
10             ## no critic (TestingAndDebugging::ProhibitNoStrict)
11 10     10   55 no strict 'refs';
  10         21  
  10         796  
12              
13 10     10   46 my @attrs = qw(
14             package
15             filename
16             line
17             subroutine
18             hasargs
19             wantarray
20             evaltext
21             is_require
22             hints
23             bitmask
24             );
25              
26 10         23 for my $a (@attrs) {
27 100     159   283 *{$a} = sub { my $s = shift; return $s->{$a} };
  100         6692  
  159         4562  
  159         492  
28             }
29             }
30              
31             {
32             my @args = qw(
33             package
34             filename
35             line
36             subroutine
37             hasargs
38             wantarray
39             evaltext
40             is_require
41             hints
42             bitmask
43             );
44              
45             sub new {
46 74     74 0 588 my $proto = shift;
47 74   33     206 my $class = ref $proto || $proto;
48              
49 74         134 my $self = bless {}, $class;
50              
51 74         96 @{$self}{@args} = @{ shift() };
  74         465  
  74         131  
52 74         139 $self->{args} = shift;
53 74         160 $self->{respect_overload} = shift;
54 74         131 $self->{max_arg_length} = shift;
55 74         127 $self->{message} = shift;
56 74         123 $self->{indent} = shift;
57              
58             # fixup unix-style paths on win32
59 74         281 $self->{filename} = File::Spec->canonpath( $self->{filename} );
60              
61 74         448 return $self;
62             }
63             }
64              
65             sub args {
66 34     34 1 69 my $self = shift;
67              
68 34         48 return @{ $self->{args} };
  34         115  
69             }
70              
71             sub as_string {
72 37     37 1 51 my $self = shift;
73 37         50 my $first = shift;
74 37         48 my $p = shift;
75              
76 37         66 my $sub = $self->subroutine;
77              
78             # This code stolen straight from Carp.pm and then tweaked. All
79             # errors are probably my fault -dave
80 37 100       76 if ($first) {
81             $sub
82             = defined $self->{message}
83             ? $self->{message}
84 15 100       44 : 'Trace begun';
85             }
86             else {
87              
88             # Build a string, $sub, which names the sub-routine called.
89             # This may also be "require ...", "eval '...' or "eval {...}"
90 22 50       45 if ( my $eval = $self->evaltext ) {
    50          
91 0 0       0 if ( $self->is_require ) {
92 0         0 $sub = "require $eval";
93             }
94             else {
95 0         0 $eval =~ s/([\\\'])/\\$1/g;
96 0         0 $sub = "eval '$eval'";
97             }
98             }
99             elsif ( $sub eq '(eval)' ) {
100 0         0 $sub = 'eval {...}';
101             }
102              
103             # if there are any arguments in the sub-routine call, format
104             # them according to the format variables defined earlier in
105             # this file and join them onto the $sub sub-routine string
106             #
107             # We copy them because they're going to be modified.
108             #
109 22 100       52 if ( my @a = $self->args ) {
110 16         38 for (@a) {
111              
112             # set args to the string "undef" if undefined
113 23 100       55 unless ( defined $_ ) {
114 2         3 $_ = 'undef';
115 2         5 next;
116             }
117              
118             # hack!
119             ## no critic (Subroutines::ProtectPrivateSubs)
120 21 50       48 $_ = $self->Devel::StackTrace::_ref_to_string($_)
121             if ref $_;
122             ## use critic;
123              
124             ## no critic (Variables::RequireInitializationForLocalVars)
125 21         61 local $SIG{__DIE__};
126 21         34 local $@;
127             ## use critic;
128              
129             ## no critic (ErrorHandling::RequireCheckingReturnValueOfEval)
130 21         35 eval {
131             my $max_arg_length
132             = exists $p->{max_arg_length}
133             ? $p->{max_arg_length}
134 21 100       56 : $self->{max_arg_length};
135              
136 21 100 66     55 if ( $max_arg_length
137             && length $_ > $max_arg_length ) {
138             ## no critic (BuiltinFunctions::ProhibitLvalueSubstr)
139 2         5 substr( $_, $max_arg_length ) = '...';
140             }
141              
142 21         47 s/'/\\'/g;
143              
144             # 'quote' arg unless it looks like a number
145 21 100       104 $_ = "'$_'" unless /^-?[\d.]+$/;
146              
147             # print control/high ASCII chars as 'M-' or '^'
148 21         58 s/([\200-\377])/sprintf("M-%c",ord($1)&0177)/eg;
  0         0  
149 21         46 s/([\0-\37\177])/sprintf("^%c",ord($1)^64)/eg;
  0         0  
150             };
151             ## use critic
152              
153 21 50       85 if ( my $e = $@ ) {
154 0 0       0 $_ = $e =~ /malformed utf-8/i ? '(bad utf-8)' : '?';
155             }
156             }
157              
158             # append ('all', 'the', 'arguments') to the $sub string
159 16         52 $sub .= '(' . join( ', ', @a ) . ')';
160 16         29 $sub .= ' called';
161             }
162             }
163              
164             # If the user opted into indentation (a la Carp::confess), pre-add a tab
165 37 100 100     113 my $tab = $self->{indent} && !$first ? "\t" : q{};
166              
167 37         92 return "${tab}$sub at " . $self->filename . ' line ' . $self->line;
168             }
169              
170             1;
171              
172             # ABSTRACT: A single frame in a stack trace
173              
174             __END__