File Coverage

lib/Devel/ebug/Plugin/FoldedStackTrace.pm
Criterion Covered Total %
statement 15 42 35.7
branch 0 6 0.0
condition n/a
subroutine 5 9 55.5
pod 0 1 0.0
total 20 58 34.4


line stmt bran cond sub pod time code
1             package Devel::ebug::Plugin::FoldedStackTrace;
2              
3 1     1   1646 use strict;
  1         2  
  1         40  
4 1     1   5 use base qw(Exporter);
  1         2  
  1         104  
5              
6             our @EXPORT = qw(folded_stack_trace);
7              
8             =head1 NAME
9              
10             Devel::ebug::Plugin::FoldedStackTrace - programmer-friendly stack traces
11              
12             =head1 SYNOPSIS
13              
14             my @folded_frames = $ebug->folded_stack_trace;
15             foreach my $frame ( @folded_frames ) {
16             # use all Devel::StackTraceFrame accessor, plus
17             # caller_package caller_subroutine caller_filename caller_line
18             # current_package current_subroutine current_filename current_line
19             }
20             # main's current_subroutine is 'MAIN::'
21             print $folded_frame[-1]->current_subroutine;
22              
23             =head1 DESCRIPTION
24              
25             Each C object in a stack trace includes some
26             information about the caller and some information about the current
27             frame, and remembering which information lies where is hard. Plus,
28             some information about the topmost (main or similar) stack frame is
29             missing.
30              
31             This plugin provides an easier-to use C subclass.
32              
33             =cut
34              
35 1     1   988 use Devel::StackTrace;
  1         3476  
  1         182  
36              
37             # folds current/caller frame in every item, includes main and
38             # current frame
39             sub folded_stack_trace {
40 0     0 0   my( $self ) = @_;
41 0           my @frames = $self->stack_trace;
42 0           my @folded = Devel::ebug::Plugin::Wx::StackTraceFrame
43             ->fold_frame_list( $self, @frames );
44              
45 0           return @folded;
46             }
47              
48             package Devel::ebug::Plugin::Wx::StackTraceFrame;
49              
50 1     1   10 use strict;
  1         2  
  1         43  
51 1     1   5 use base qw(Devel::StackTraceFrame Class::Accessor::Fast);
  1         1  
  1         890  
52              
53             __PACKAGE__->mk_ro_accessors
54             ( qw(caller_package current_package caller_subroutine current_subroutine
55             caller_filename current_filename caller_line current_line) );
56              
57             sub new {
58 0     0     my( $class, $args ) = @_;
59 0           my $self = bless { %$args }, $class;
60              
61 0           return $self;
62             }
63              
64             sub new_from_frame {
65 0     0     my( $class, $frame ) = @_;
66 0           my $self = bless { %$frame }, $class;
67              
68 0           $self->{current_subroutine} = $self->{subroutine};
69 0           $self->{caller_package} = $self->{package};
70 0           $self->{caller_filename} = $self->{filename};
71 0           $self->{caller_line} = $self->{line};
72              
73 0           return $self;
74             }
75              
76             sub fold_frame_list {
77 0     0     my( $class, $ebug, @frames ) = @_;
78 0           my @folded = map $class->new_from_frame( $_ ), @frames;
79              
80             # main
81 0 0         push @folded, $class->new
    0          
    0          
82             ( { current_package => @frames ? $frames[-1]->package : undef,
83             current_filename => @frames ? $frames[-1]->filename : undef,
84             current_line => @frames ? $frames[-1]->line : undef,
85             current_subroutine => 'MAIN::',
86             args => [],
87             } );
88             # current
89 0           $folded[0]->{current_package} = $ebug->package;
90 0           $folded[0]->{current_filename} = $ebug->filename;
91 0           $folded[0]->{current_line} = $ebug->line;
92              
93             # propagate current_* down the call chain
94 0           for( my $i = 1; $i < @folded; ++$i ) {
95 0           $folded[$i]->{current_package} = $folded[$i-1]->caller_package;
96 0           $folded[$i]->{current_filename} = $folded[$i-1]->caller_filename;
97 0           $folded[$i]->{current_line} = $folded[$i-1]->caller_line;
98             }
99              
100             # propagate caller_subroutine up the call chain
101 0           for( my $i = @folded - 1; $i > 0; --$i ) {
102 0           $folded[$i-1]->{caller_subroutine} = $folded[$i]->current_subroutine;
103             }
104              
105 0           return @folded;
106             }
107              
108             1;