Devel-CompiledCalls

 view release on metacpan or  search on metacpan

lib/Devel/CompiledCalls.pm  view on Meta::CPAN

	cv_get_call_checker
	cv_set_call_checker
);
use Sub::Identify qw(sub_fullname);

our $VERSION = "2.00";

=head1 NAME

Devel::CompiledCalls - show where calls to a named subroutine are compiled

=head1 SYNOPSIS

  # from the shell
  shell$ perl -c -MDevel::CompiledCalls=Data::Dumper::Dumper myscript.pl
  Data::Dumper::Dumper call at myscript.pl line 4.
  Data::Dumper::Dumper call at myscript.pl line 5.
  myscript.pl syntax OK

  # from within a Perl script
  use Devel::CompiledCalls qw(Data::Dumper::Dumper);

  # from a perl script with custom callback
  use Devel::CompiledCalls;
  BEGIN {
    Devel::CompiledCalls::attach_callback("Data::Dumper::Dumper", sub {
      my ($subname, $filename, $line) = @_;
      say "$subname at $line of $filename";
    });
  };

=head1 DESCRIPTION

This module allows you to put hooks into Perl so that whenever a call to
a named subroutine has been compiled a callback is fired.  The easiest syntax
(import Devel::CompiledCalls and pass the name of the subroutine) simply
logs the line and filename of the call to STDERR.

Note that since we are hooking the process of compiling not the execution of
the subroutines (technically, we're hooking the process of subroutine parameter
checking, but the effects are the same) this module will find calls that aren't
normally captured by modules like Hook::LexWrap because they're not normally
executed during the program's execution (e.g. a call in exception handling code
that only occurs once every four years.)

=head2 Use with import

The simpliest way to to hook is to pass the name of the function in the
import list:

    use Devel::CompiledCalls qw(foo);
    ...

Or from the command line:

    perl -MDevel::CompiledCalls=foo -e '...'

In both these cases the standard callback - which simply prints to STDERR - will
be installed.

=head2 Custom callbacks

Custom callbacks can be installed with the C<attach_callback> subroutine.
This routine is not exported and must be called with a fully qualified
function call.

=over

=item attach_callback( $subroutine_ref, $callback )

=item attach_callback( $subroutine_name, $callback )

The callback will be called whenever a call to the subroutine is compiled.  The
subroutine can either be passed by reference, by fully qualified name (including
the package,) or by just the subroutine name (in which case it will be assumed
to be in the same package as C<attach_callback> is called from.)

The callback will be executed with three parameters: The name of the subroutine,
the filename of the source file, and the the line of the sourcefile that
contains the subroutine.

=back

=cut

sub import {
	shift;
	attach_callback($_, sub {
		my ($name, $file, $line,$stash) = @_;
		local $\ = undef;  # locally reset back to default just in case
		print {*STDERR} "$name call at $file line $line.\n";
	}) foreach @_;
	return;
}

sub attach_callback {
	my $name = shift;
	my $callback = shift;

	# check for an unqualifed subroutine name.  If we have one
	# then we need to give it our *caller's* package (or, potentially
	# our caller's caller package
	my $fully_qualified_name =
		ref $name eq "CODE" ? $name :
		$name =~ /::/x      ? $name  : do {
			my $caller_package;
			my $level = 1;
			do { ($caller_package) = caller($level++) }
				while ($caller_package eq __PACKAGE__);
			$caller_package.'::'.$name;
		};
	$name = sub_fullname($name) if ref($name) eq "CODE";

	# get the sub (this will spring into existence with autovivication
	# if needed)
	my $uboat = do { no strict 'subs'; \&{$fully_qualified_name} };

	# work out what original check would have been made
	my ($original_check, $data) = cv_get_call_checker($uboat);

	# install our own checker that doesn't actually do any checking
	# but instead simply calls the callback
	cv_set_call_checker($uboat, sub {



( run in 1.076 second using v1.01-cache-2.11-cpan-6aa56a78535 )