Our codebase includes various debugging hooks that should only be used for testing. As an illustrative example:
sub example {
my ($arg) = @_;
my $result = do_something_with($arg);
debug_dump_values($arg); # debugging code
return $result;
}
Of course, such debugging code should not be committed (or even deployed). Is there a way to generate a warning when running this code through perl -c
? Something along the lines of
Debug function debug_dump_values() called at example.pl line 4.
This would be trivial to implement as a runtime warning:
sub debug_dump_values {
carp "Debug function debug_dump_values() called";
...
}
But I want a warning that shows up in my text editor through its syntax check plugin, so it needs to be a "compile-time" warning.
I think this isn't an easy thing to accomplish - it's not going to be possible without some significant rejigging of coding style.
Approaches I can think of:
Embed a warning in the module that indicates it's enabled - embed within a 'BEGIN' block. (This won't necessarily tell you which sub is being called though, nor where)
E.g.
BEGIN {
carp "Debugging module is imported"
}
Advantages of this might be - you can have a 'debug' and 'not debug' module, and have the same subs in both. The 'not debug' would put in dummy subs.
You can then use B::Lint
to validate your module and check if subs are all defined:
perl -MO=Lint[,OPTIONS] foo.pl
undefined-subs
This option warns whenever an undefined subroutine is invoked. This option will only catch explicitly invoked subroutines such as foo() and not indirect invocations such as &$subref() or $obj->meth() . Note that some programs or modules delay definition of subs until runtime by means of the AUTOLOAD mechanism
Edit: Doesn't work as well as I thought - had a notion of declaring anonymous subs and creating references within 'BEGIN' blocks - that doesn't work as well as I thought - it only errors at runtime, because you get errors of scope.
Best I can offer is:
use strict;
use warnings;
my $debug = 1;
##debug code bit.
#Comment out if not needed
my $debug_sub = gimme_debug();
sub gimme_debug {
if ( $debug ) {
warn "Debugging enabled\n";
return sub { print "Got values of :", @_, "\n"; };
}
else { warn "Debug subroutine defined with debug disabled!" };
}
#... way down code ...
&$debug_sub ( "Some input" );
If you remove the declaration of then you'll get a compile time warning because $debug_sub
is undeclared. This might combine with the above, e.g. bundling it in a module or object.
It doesn't do specifically what you asked about, however you may want to consider it anyway. Automated testing for your code/modules. For example, using TAP::Harness
. It's a bit more complicated and intensive than what you're asking, but having something that'll automatically trap debug code (and otherwise validate the various components of your code) is probably the 'right' way to do it.
I've also heard of (but not done much with) Class::Inspector
which may be suitable for your needs.
But I think at a fairly fundamental level - what you're trying to do isn't checked at compile time, because it's very difficult to evaluate which bits of code are actually being called without actually running the code. So anything you do like this would be something you have to 'hand manage' in some fashion.
"In computability theory, the halting problem is the problem of determining, from a description of an arbitrary computer program and an input, whether the program will finish running or continue to run forever.
Alan Turing proved in 1936 that a general algorithm to solve the halting problem for all possible program-input pairs cannot exist. A key part of the proof was a mathematical definition of a computer and program, which became known as a Turing machine; the halting problem is undecidable over Turing machines. It is one of the first examples of a decision problem."
So if you do come up with a good solution to this - there's probably a usefully large prize on offer :).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With