File Coverage

lib/Devel/ebug/Plugin/StackTrace.pm
Criterion Covered Total %
statement 45 53 84.9
branch 19 22 86.3
condition 9 18 50.0
subroutine 7 7 100.0
pod 0 3 0.0
total 80 103 77.6


line stmt bran cond sub pod time code
1             package Devel::ebug::Plugin::StackTrace;
2              
3 19     19   11422 use strict;
  19         41  
  19         572  
4 19     19   89 use warnings;
  19         32  
  19         581  
5 19     19   97 use Scalar::Util qw(blessed);
  19         30  
  19         1166  
6 19     19   118 use base qw(Exporter);
  19         44  
  19         19196  
7             our @EXPORT = qw(stack_trace stack_trace_human stack_trace_human_args);
8              
9             our $VERSION = '0.63'; # VERSION
10              
11             # return the stack trace
12             sub stack_trace {
13 16     16 0 118 my($self) = @_;
14 16         113 my $response = $self->talk({ command => "stack_trace" });
15 16 50       54 return @{$response->{stack_trace}||[]};
  16         117  
16             }
17              
18             # return the stack trace in a human-readable format
19             sub stack_trace_human {
20 14     14 0 16542 my($self) = @_;
21 14         26 my @human;
22 14         49 my @stack = $self->stack_trace;
23 14         79 foreach my $frame (@stack) {
24 15         130 my $subroutine = $frame->subroutine;
25 15         150 my $package = $frame->package;
26 15         147 my @args = $frame->args;
27 15         119 my $first = $args[0];
28 15         35 my $first_class = ref($first);
29 15         155 my($subroutine_class, $subroutine_method) = $subroutine =~ /^(.+)::([^:])+?$/;
30             # warn "first: $first, first class: $first_class, package: $package, subroutine: $subroutine ($subroutine_class :: $subroutine_method)\n";
31              
32 15 50 66     462 if (defined $first && blessed($first) && $subroutine =~ /^${first_class}::/ &&
    50 33        
    100 33        
    100 66        
      33        
      66        
33             $subroutine =~ /^$package/) {
34 0         0 $subroutine =~ s/^${first_class}:://;
35 0         0 shift @args;
36 0         0 push @human, "\$self->$subroutine" . $self->stack_trace_human_args(@args);
37             } elsif (defined $first && blessed($first) && $subroutine =~ /^${first_class}::/) {
38 0         0 $subroutine =~ s/^${first_class}:://;
39 0         0 shift @args;
40 0         0 my($name) = $first_class =~ /([^:]+)$/;
41 0         0 $first = '$' . lc($name);
42 0         0 push @human, "$first->$subroutine" . $self->stack_trace_human_args(@args);
43             } elsif ($subroutine =~ s/^${package}:://) {
44 11         71 push @human, "$subroutine" . $self->stack_trace_human_args(@args);
45             } elsif (defined $first && $subroutine_class eq $first) {
46 1         5 shift @args;
47 1         13 push @human, "$first->new" . $self->stack_trace_human_args(@args);
48             } else {
49 3         29 push @human, "$subroutine" . $self->stack_trace_human_args(@args);
50             }
51             }
52 14         132 return @human;
53             }
54              
55             sub stack_trace_human_args {
56 42     42 0 109 my($self, @args) = @_;
57 42         95 foreach my $arg (@args) {
58 40 100       317 if (not defined $arg) {
    100          
    100          
    100          
    100          
    100          
59 3         33 $arg = "undef";
60             } elsif (ref($arg) eq 'ARRAY') {
61 1         4 $arg = "[...]";
62             } elsif (ref($arg) eq 'HASH') {
63 1         4 $arg = "{...}";
64             } elsif (ref($arg)) {
65 10         68 my($name) = ref($arg) =~ /([^:]+)$/;
66 10         40 $arg = '$' . lc($name);
67             } elsif ($arg =~ /^-?[\d.]+$/) {
68             # number, do nothing
69             } elsif ($arg =~ /^[\w:]*$/) {
70 2         6 $arg =~ s/([\'\\])/\\$1/g;
71 2         9 $arg = qq{'$arg'};
72             } else {
73 9         28 $arg =~ s/([\'\\])/\\$1/g;
74 9         32 $arg = qq{"$arg"};
75             }
76             }
77 42         218 return '(' . join(", ", @args) . ')';
78             }
79              
80             1;
81              
82             __END__