File Coverage

blib/lib/Devel/Events/Generator/SubTrace.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3 2     2   27488 use Moose ();
  0            
  0            
4             use Moose::Role ();
5              
6             BEGIN { $^P |= 0x01 }
7              
8             package Devel::Events::Generator::SubTrace;
9             use Moose;
10              
11             with qw/Devel::Events::Generator/;
12              
13             use Scalar::Util ();
14              
15             my ( $SINGLETON );
16             our ( $IGNORE, $DEPTH ); # can't local a lexical ;_;
17              
18             BEGIN { $DEPTH = -1 };
19              
20             {
21             package DB;
22              
23             our $sub;
24              
25             sub sub {
26             local $DEPTH = $DEPTH + 1;
27              
28             unless ( $SINGLETON
29             and !$IGNORE,
30             and $sub !~ /^Devel::Events::/
31             ) {
32             no strict 'refs';
33             goto &$sub;
34             }
35              
36             my @ret;
37             my $ret;
38              
39             my $tsub ="$sub";
40             $tsub = 'main' unless $tsub;
41              
42             my @args = (
43             'name' => "$tsub",
44             'code' => \&$tsub,
45             'args' => [ @_ ],
46             'depth' => $DEPTH,
47             'wantarray' => wantarray(),
48             );
49              
50             push @args, autoload => do { no strict 'refs'; $$tsub }
51             if (( length($tsub) > 10) && (substr( $tsub, -10, 10 ) eq '::AUTOLOAD' ));
52              
53             $SINGLETON->enter_sub(@args);
54              
55             {
56             no strict 'refs';
57              
58             if (wantarray) {
59             @ret = &$sub;
60             }
61             elsif (defined wantarray) {
62             $ret = &$sub;
63             }
64             else {
65             &$sub;
66             }
67             }
68              
69             $SINGLETON->leave_sub(
70             @args,
71             ret => (wantarray) ? \@ret : defined(wantarray) ? $ret : undef,
72             );
73              
74             return (wantarray) ? @ret : defined(wantarray) ? $ret : undef;
75             }
76             }
77              
78             sub enter_sub {
79             my ( $self, @data ) = @_;
80             local $IGNORE = 1;
81              
82             $self->send_event( enter_sub => @data );
83             }
84              
85             sub leave_sub {
86             my ( $self, @data ) = @_;
87             local $IGNORE = 1;
88              
89             $self->send_event( leave_sub => @data );
90             }
91              
92             sub enable {
93             my $self = shift;
94             local $IGNORE = 1;
95             $SINGLETON = $self;
96             Scalar::Util::weaken($SINGLETON);
97             }
98              
99             sub disable {
100             $SINGLETON = undef;
101             }
102              
103             __PACKAGE__;
104              
105             __END__
106              
107              
108             =pod
109              
110             =head1 NAME
111              
112             Devel::Events::Generator::SubTrace - generate C<executing_line> events using
113             the perl debugger api.
114              
115             =head1 SYNOPSIS
116              
117             my $g = Devel::Events::Generator::SubTrace->new( handler => $h );
118              
119             $g->enable();
120              
121             # every subroutine will have two events fired, on entry and exit
122              
123             $g->disable();
124              
125             =head1 DESCRIPTION
126              
127             This L<Devel::Events> generator will fire sub tracing events using C<DB::sub>,
128             a perl debugger hook.
129              
130             Only one instance may be enabled at a given time. Use
131             L<Devel::Events::Handler::Multiplex> to deliver events to multiple handlers.
132              
133             Subroutines inside the L<Devel::Events> namespace or it's children will be
134             skipped.
135              
136             =head1 EVENTS
137              
138             =over 4
139              
140             =item enter_sub
141              
142             When the generator is enabled, this event will fire for every subroutine, just
143             before it is executed.
144              
145             Subroutines in a package starting with C<Devel::Events::> will not be reported.
146              
147             =over 4
148              
149             =item name
150              
151             The name of the subroutine (or it's C<overload::StrVal> if it has none).
152              
153             =item code
154              
155             A code reference to the subroutine.
156              
157             =item args
158              
159             A copy of the arguments list. C<\@_> causes segfaults but C<[ @_ ]> does not.
160             Bummer ;-)
161              
162             =item depth
163              
164             The current depth of the call stack.
165              
166             =item wantarray
167              
168             The context of the call as given by C<wantarray>
169              
170             =back
171              
172             =item leave_sub
173              
174             Exactly like C<enter_sub>, but fired just after leaving the subroutine.
175              
176             =over 4
177              
178             All the fields of C<enter_sub> are passed.
179              
180             Additional fields:
181              
182             =item ret
183              
184             The return value of the subroutine.
185              
186             =back
187              
188             =back
189              
190             =head1 METHODS
191              
192             =over 4
193              
194             =item enable
195              
196             Enable this generator instance, disabling any other instance of
197             L<Devel::Events::Generator::SubTrace>.
198              
199             =item disable
200              
201             Stop firing events.
202              
203             =item enter_sub
204              
205             Called by C<DB::sub>. Sends the C<enter_sub> event.
206              
207             =item leave_sub
208              
209             Called by C<DB::sub>. Sends the C<leave_sub> event.
210              
211             =back
212              
213             =head1 SEE ALSO
214              
215             L<perldebguts>, L<Devel::CallTrace>, L<DB>, L<Devel::ebug>, L<perl5db.pl>
216              
217             =cut