File Coverage

blib/lib/Sub/Information.pm
Criterion Covered Total %
statement 113 129 87.6
branch 22 36 61.1
condition n/a
subroutine 26 28 92.8
pod 3 3 100.0
total 164 196 83.6


line stmt bran cond sub pod time code
1             package Sub::Information;
2              
3 4     4   116860 use warnings;
  4         11  
  4         143  
4 4     4   21 use strict;
  4         10  
  4         117  
5              
6 4     4   25 use Scalar::Util ();
  4         9  
  4         509  
7 4     4   21 use B;
  4         6  
  4         230  
8              
9 4     4   112 use 5.006; # need the warnings pragma :(
  4         22  
  4         539  
10              
11             =head1 NAME
12              
13             Sub::Information - Get subroutine information
14              
15             =head1 VERSION
16              
17             Version 0.10
18              
19             =cut
20              
21             our $VERSION = '0.10';
22              
23             =head1 SYNOPSIS
24              
25             use Sub::Information as => 'inspect';
26              
27             my $code_info = inspect(\&code);
28             print $code_info->name;
29             print $code_info->package;
30             print $code_info->code;
31             print $code_info->address;
32             # etc.
33              
34             =head1 DESCRIPTION
35              
36             Typically, if we need to get information about code references, we have to
37             remember which of myriad modules to load. Need to know if it's blessed?
38             C will do that. Package it was declared in: C.
39             Source code: C. And so on ...
40              
41             This module integrates those together so that you don't have to remember them.
42              
43             =head1 EXPORT
44              
45             By default, we export the C function. This function, when called on
46             a code reference, will 'inspect' the code reference and return a
47             C object. If you already have an C function, you can
48             rename the function by specifying C<< as => 'other_func' >> in the import
49             list. The following are equivalent:
50              
51             use Sub::Information; # exports 'inspect'
52             my $info = inspect($coderef);
53              
54             Or:
55              
56             use Sub::Information (); # don't import anything
57             my $info = Sub::Information->new($coderef);
58              
59             Or:
60            
61             use Sub::Information as => 'peek'; # exports 'peek'
62             my $info = peek($coderef);
63              
64             =head1 FUNCTIONS
65              
66             =head2 C
67              
68             my $info = inspect($coderef);
69              
70             Given a code reference, this function returns a new C
71             object.
72              
73             =head1 METHODS
74              
75             =head2 Class Methods
76              
77             =head3 C
78              
79             my $info = Sub::Information->new($coderef);
80              
81             Returns a new C object.
82              
83             =head2 Instance Methods
84              
85             Unless otherwise stated, all methods cache their return values and the modules
86             they rely on are I loaded until needed. Please see the documentation of
87             the original module for more information about how the method behaves.
88              
89             =head3 C
90              
91             my $address = $info->address;
92              
93             Returns the memory address, in decimal, of the original code reference.
94              
95             From: C
96              
97             =head3 C
98              
99             my $blessed = $info->blessed;
100              
101             Returns the package name a coderef is blessed into. Returns undef if the
102             coderef is not blessed.
103              
104             From: C
105              
106             =head3 C
107              
108             my $source_code = $info->code;
109              
110             Returns the source code of the code reference. Because of how it's generated,
111             it should be equivalent in functionality to the original code reference, but
112             may appear different. For example:
113              
114             sub add_2 { return 2 + shift }
115             print inspect(\&add_2)->code;
116              
117             __END__
118             # output
119             $CODE1 = sub {
120             use strict 'refs';
121             return 2 + shift(@_);
122             };
123              
124             From: C
125              
126             =head3 C
127              
128             $info->dump;
129              
130             Returns the internals information regarding the coderef as generated by
131             C to STDERR. This method is experimental. Let me know if
132             it doesn't work.
133              
134             From: C
135              
136             =head3 C
137              
138             my $fullname = $info->fullname;
139              
140             Returns the fully qualified subroutine name (package + subname) of the
141             coderef.
142              
143             From: C
144              
145             =head3 C
146              
147             my $name = $info->name;
148              
149             Returns the name of the subroutine. If the subroutine is an anonymous
150             subroutine, it may return C<__ANON__>. However, you can name anonymous
151             subroutines with:
152              
153             local *__ANON__ = 'name::of::anonymous::subroutine';
154              
155             From: C
156              
157             =head3 C
158              
159             my $package = $info->package;
160              
161             Returns the name of the package the subroutine was declared in.
162              
163             From: C
164              
165             =head3 C
166              
167             my $variables = $info->variables;
168              
169             Returns all C variables found in the code reference (whether declared
170             their or outside of the code reference). The return value is a hashref whose
171             keys are the names (with sigils) of the variables and whose values are the
172             values of said variable.
173              
174             Note that those values will be undefined unless the code is currently "in use"
175             (e.g., you're calling C from inside the sub or in a call stack
176             the sub is currently in).
177              
178             The returned values are not cached.
179              
180             From: C
181              
182             =head3 C
183              
184             my $line_number = $info->line;
185              
186             Returns the approximate line number where the sub was declared. This is
187             experimental.
188              
189             From : C
190              
191             =head3 C
192              
193             my $file_name = $info->file;
194              
195             Returns the file name where the sub was declared. This is experimental.
196              
197             From : C
198              
199             =head1 CAVEATS
200              
201             This is ALPHA code.
202              
203             =over 4
204              
205             =item * Memory requirements
206              
207             Some modules, such as L, can be very expensive to load. Thus,
208             none are loaded until such time as they are needed.
209              
210             =item * Caching
211              
212             To avoid overhead, we cache all results unless otherwise noted.
213              
214             =item * Return values
215              
216             Returns values are not calculated until such time as they are requested.
217             Thus, it's possible that the value returns is not identical to the value for
218             the code reference at the time the new C instance was
219             created.
220              
221             =item * Refcount
222              
223             The C instance stores a reference to the coderef, thus
224             incrementing its refcount by 1.
225              
226             =back
227              
228             =cut
229              
230             sub import {
231 4     4   42 my ( $class, %arg_for ) = @_;
232 4         11 my $caller = caller;
233 4 100       26 unless (%arg_for) {
234 4     4   17 no strict 'refs';
  4         7  
  4         762  
235 2         4 *{"$caller\::inspect"} = \&inspect;
  2         12  
236             }
237 4 100       21 if ( defined( my $sub = delete $arg_for{as} ) ) {
238 2         7 chomp $sub;
239 2 50       21 unless ( $sub =~ /^\w+$/ ) {
240 0         0 $class->_croak("Sub '$sub' is not a valid subroutine name");
241             }
242 4     4   24 no strict 'refs';
  4         7  
  4         2674  
243 2         4 *{"$caller\::$sub"} = \&inspect;
  2         11  
244             }
245 4 50       47 if (%arg_for) {
246 0         0 my @keys = keys %arg_for;
247 0         0 local $" = ", ";
248 0         0 $class->_croak("Unknown keys to import list: (@keys)");
249             }
250             }
251              
252             my %PACKAGE_FOR;
253              
254             sub new {
255 8     8 1 45 my ( $class, $coderef ) = @_;
256 8         42 my $self = bless {
257             coderef => $coderef,
258             package_for => \%PACKAGE_FOR,
259             } => $class;
260 8         37 return $self;
261             }
262              
263             sub inspect {
264 8 50   8 1 2762 unless ( 'CODE' eq Scalar::Util::reftype $_[0] ) {
265 0         0 __PACKAGE__->_croak(
266             "Argument to Sub::Information::inspect() must be a code ref");
267             }
268 8         47 return __PACKAGE__->new(shift);
269             }
270              
271             sub _croak {
272 0     0   0 shift;
273 0         0 require Carp;
274 0         0 Carp::croak(@_);
275             }
276              
277             sub _carp {
278 0     0   0 shift;
279 0         0 require Carp;
280 0         0 Carp::carp(@_);
281             }
282              
283             BEGIN {
284             my %sub_information = (
285             address => {
286 2         12 code => sub { Scalar::Util::refaddr(shift) }
287             },
288             blessed => {
289 0         0 code => sub { Scalar::Util::blessed(shift) }
290             },
291             code => {
292 2         11 code => sub { Data::Dump::Streamer::Dump(shift)->Indent(0)->Out }
293             },
294             fullname => {
295 2         8 code => sub { Sub::Identify::sub_fullname(shift) }
296             },
297             name => {
298 2         9 code => sub { Sub::Identify::sub_name(shift) }
299             },
300             package => {
301 2         9 code => sub { Sub::Identify::stash_name(shift) }
302             },
303             variables => {
304 6         43 code => sub { PadWalker::peek_sub(shift) }
305             },
306 1         28 line => { code => sub { B::svref_2object(shift)->START->line } },
307 1         12 file => { code => sub { B::svref_2object(shift)->START->file } },
308              
309             # XXX I suspect these are useless
310             #size => { code => sub { Devel::Size::size(shift) } },
311             #total_size => { code => sub { Devel::Size::total_size(shift) } },
312 4     4   175 );
313 4         15 $sub_information{variables}{dont_cache} = 1;
314              
315             #$sub_information{size}{dont_cache} = 1;
316             #$sub_information{total_size}{dont_cache} = 1;
317              
318 4         37 my %function_from = (
319             'Scalar::Util' => [qw/address blessed/],
320             'Data::Dump::Streamer' => ['code'],
321             'Sub::Identify' => [qw/full_name name package/],
322             'PadWalker' => [qw/variables/],
323              
324             #'Devel::Size' => [qw/size total_size/],
325             );
326              
327 4         55 while ( my ( $package, $methods ) = each %function_from ) {
328 16         27 foreach my $method (@$methods) {
329 28         101 $PACKAGE_FOR{$method} = $package;
330             }
331             }
332              
333 4         23 while ( my ( $method, $value_for ) = each %sub_information ) {
334 4     4   23 no strict 'refs';
  4         9  
  4         818  
335             *$method = sub {
336 18     18   2865 my $self = shift;
337 18 100       70 if ( my $package = $PACKAGE_FOR{$method} ) {
338 14     3   1209 eval "use $package";
  3     3   4747  
  3     2   2909  
  3     2   83  
  3     2   18  
  3     2   5  
  3     2   60  
  2         3362  
  2         152472  
  2         19  
  2         16  
  2         5  
  2         84  
  2         13  
  2         4  
  2         59  
  2         11  
  2         4  
  2         50  
  2         12  
  2         4  
  2         57  
339 14 50       320 if ( my $error = $@ ) {
340 0         0 $self->_carp(
341             "Skipping $method. Could not load source package $package: $error"
342             );
343 0         0 return;
344             }
345             }
346 18 50       120 unless ( exists $self->{value_for}{$method} ) {
347 18         71 my $result = $value_for->{code}( $self->{coderef} );
348 18 100       11800 return $result if $value_for->{dont_cache};
349 12         103 $self->{value_for}{$method} = $result;
350             }
351 12         91 return $self->{value_for}{$method};
352 36         1057 };
353             }
354             }
355              
356             {
357              
358             my $peek_loaded;
359              
360             sub _require_devel_peek {
361 1     1   3 my $self = shift;
362 1 50       5 return 1 if $peek_loaded;
363 1         91 eval <<' LOAD_DEVEL_PEEK';
364             package Sub::Information::_Internal;
365             use Devel::Peek;
366             LOAD_DEVEL_PEEK
367 1 50       118 if ( my $error = $@ ) {
368 0         0 $self->_carp(
369             "Skipping dump. Could not load source package Devel::Peek: $error"
370             );
371 0         0 return;
372             }
373 1         6 return $peek_loaded = 1;
374             }
375             }
376              
377             # $stderr = _capture_stderr({ code to be executed })
378             #
379             sub _capture_stderr {
380 1     1   3 my $code = shift;
381 1 50       3 die "undef code !?" unless $code;
382              
383 1         2 my $stderr; # XXX " open H, '>', \$var " requires 5.8+
384              
385 4     4   23 no warnings 'once'; # perl thinks SAVEERR is used just once
  4         7  
  4         927  
386              
387             # save STDERR for restoring later
388 1 50       18 open SAVEERR, "<&=STDERR" or die "error duping STDERR: $!";
389 1 50       5 close STDERR or die "error closing STDERR: $!";
390             {
391 1         2 local *STDERR;
  1         3  
392              
393             # open STDERR to in-memory file
394 1 50       27 open STDERR, ">", \$stderr
395             or die "error opening STDERR to in-memory file: $!"; # XXX
396              
397 1         1312 $code->();
398              
399 1 50       6 close STDERR or die "error closing in-memory file: $!";
400             }
401              
402             # restore STDERR
403 1 50       15 open STDERR, ">&=SAVEERR" or die "error restoring STDERR: $!";
404              
405 1         10 return $stderr;
406             }
407              
408             sub dump {
409 1     1 1 869 my $self = shift;
410 1 50       23 return unless $self->_require_devel_peek;
411              
412             return _capture_stderr sub {
413 4     4   20 no warnings 'uninitialized';
  4         9  
  4         375  
414 1     1   99 Sub::Information::_Internal::Dump( $self->{coderef} );
415 1         7 }; # XXX STDERR may be borken
416              
417             }
418              
419             =head1 AUTHOR
420              
421             Curtis "Ovid" Poe, C<< >>
422              
423             =head1 BUGS
424              
425             Please report any bugs or feature requests to
426             C, or through the web interface at
427             L.
428             I will be notified, and then you'll automatically be notified of progress on
429             your bug as I make changes.
430              
431             =head1 TODO
432              
433             Probably lots. Send patches, ideas, criticisms, whatever.
434              
435             =head1 SEE ALSO
436              
437             Several of the following modules are either used internally or may be of
438             further interest to you.
439              
440             =over 4
441              
442             =item * L
443              
444             =item * L
445              
446             =item * L
447              
448             =item * L
449              
450             =item * L
451              
452             =item * L
453              
454             =item * L
455              
456             =back
457              
458             =head1 THANKS
459              
460             Much appreciation to Adriano Ferreira for providing two very useful patches.
461              
462             =head1 COPYRIGHT & LICENSE
463              
464             Copyright 2007 Curtis "Ovid" Poe, all rights reserved.
465              
466             This program is free software; you can redistribute it and/or modify it
467             under the same terms as Perl itself.
468              
469             =cut
470              
471             1; # End of Sub::Information