File Coverage

lib/Devel/TraceMethods.pm
Criterion Covered Total %
statement 44 46 95.6
branch 9 10 90.0
condition 7 12 58.3
subroutine 8 8 100.0
pod 1 1 100.0
total 69 77 89.6


line stmt bran cond sub pod time code
1             package Devel::TraceMethods;
2              
3 2     2   1529 use strict;
  2         5  
  2         97  
4              
5 2     2   12 use vars '$VERSION';
  2         4  
  2         376  
6             $VERSION = '1.00';
7              
8             sub import
9             {
10 6     6   3625 my $package = shift;
11              
12 6         38 while (@_)
13             {
14 4         10 my $traced = shift;
15 4 100 66     28 my $logger = ref $_[0] eq 'CODE' && defined &{ $_[0] } ? shift : undef;
16 4         11 _wrap_symbol( $traced, $logger );
17             }
18             }
19              
20             sub _wrap_symbol
21             {
22 4     4   8 my ($traced, $logger) = @_;
23 4         7 my $src;
24              
25             # get the calling package symbol table name
26             {
27 2     2   21 no strict 'refs';
  2         4  
  2         1123  
  4         6  
28 4         6 $src = \%{ $traced . '::' };
  4         14  
29             }
30              
31             # loop through all symbols in calling package, looking for subs
32 4         14 for my $symbol ( keys %$src )
33             {
34             # get all code references, make sure they're valid
35 11         15 my $sub = *{ $src->{$symbol} }{CODE};
  11         51  
36 11 100 66     82 next unless defined $sub and defined &$sub;
37              
38             # save all other slots of the typeglob
39 8         10 my @slots;
40              
41 8         221 for my $slot (qw( SCALAR ARRAY HASH IO FORMAT ))
42             {
43 40         40 my $elem = *{ $src->{$symbol} }{$slot};
  40         290  
44 40 100       145 next unless defined $elem;
45 8         18 push @slots, $elem;
46             }
47              
48             # clear out the source glob
49 8         25 undef $src->{$symbol};
50              
51             # replace the sub in the source
52             $src->{$symbol} = sub
53             {
54 6     6   1036 my @args = @_;
55 6         34 _log_call->(
56             name => "${traced}::$symbol",
57             logger => $logger,
58             args => [ @_ ]
59             );
60 6         45 return $sub->(@_);
61 8         49 };
62              
63             # replace the other slot elements
64 8         16 for my $elem (@slots)
65             {
66 8         40 $src->{$symbol} = $elem;
67             }
68             }
69             }
70              
71             {
72             my $logger = sub { require Carp; Carp::carp( join ', ', @_ ) };
73              
74             # set a callback sub for logging
75             sub callback
76             {
77             # should allow this to be a class method :)
78 3 100   3 1 1263 shift if @_ > 1;
79              
80 3         6 my $coderef = shift;
81 3 50 33     29 unless( ref($coderef) eq 'CODE' and defined(&$coderef) )
82             {
83 0         0 require Carp;
84 0         0 Carp::croak( "$coderef is not a code reference!" );
85             }
86              
87 3         10 $logger = $coderef;
88             }
89              
90             # where logging actually happens
91             sub _log_call
92             {
93 6     6   24 my %args = @_;
94 6   66     32 my $log_sub = $args{logger} || $logger;
95              
96 6         9 $log_sub->( $args{name}, @{ $args{args} });
  6         22  
97             }
98             }
99              
100             1;
101              
102             __END__