In response to this SoPW node, I felt compelled to invent something simple and quick that would scan a perl script and report any cases where "my" was used to declare the same variable name more than once.
This approach is not subtle or discerning -- just check all easily-identifyable uses of "my" with variable names, and keep these (with line numbers) in a hash. When done scanning the script, report the cases with more than one line number. (There is also the "--listall" option, which does what you would expect...)
Caveats (at least, the ones I know of):
- The line numbers being reported are based on the output of B::Deparse, where all commentary has been stripped, and spacing and punctuation have been normalized. This means you may need to work a little harder to relate this diagnosis to your original script, but doing it this way helps me make the search for "my" a lot less speculative (and I do save the Deparsed version of the script in a separate file, so you can actually use the line-number info that is being given).
- There are bound to be other ways that "my" shows up in a "deparsed" script besides the ones being searched for in this version, so there may be some "misses".
- Someone is bound to try this on a script containing a quoted literal string that looks like a "my" declaration, so there may be some false alarms as well.
- This doesn't pay any attention to scope. If you use anything like foreach my $arg ( @list ) in multiple places in your script, and these are all sensible and proper, this diagnosis will cite them all as "repeats" anyway -- better to be stupid and safe, I think.
That said, here's the code (tested on a few scripts):
#!/usr/bin/perl # Program: scan-perl-vars.perl # Written by: dave graff # Purpose: look for and summarize the declarations and calls # of lexically-scoped variables in a perl script use strict; my $Usage = "$0 [--listall] my_script.perl\n". " will list 'my' vars that have been declared more than once in a +script\n". " (with --listall, will list all lexical variables, with line numb +ers)\n"; my $listyp = ' more than once'; if ( @ARGV > 1 and $ARGV[0] eq '--listall' ) { $listyp = ''; shift; } die $Usage unless ( @ARGV == 1 && -r $ARGV[0] ); my $erlog = "/tmp/scn-src.$$.errlog"; my $file = shift; warn "Deparsing $file...\n"; my @lines = `perl -MO=Deparse,-p $file 2> $erlog`; die "Nothing deparsed from $file -- sorry.\n" unless ( @lines ); my $log = `cat $erlog`; die "Syntax errors in $file -- come back when you're ready.\n" unless ( $log =~ /^$file syntax OK/ ); # Store an array of subroutine defs in a hash element # keyed by file name: my %vardecs; # HoA keyed by var name, stores line #(s) of declaration +(s) my $lineno = 0; open( DP, ">$file.deparse" ) or warn "couldn't write deparsed code to +$file.deparse:$!\n"; foreach (@lines) { $lineno++; print DP "$lineno\t$_"; while (( my $nxt = index( $_, 'my' )) >= 0 ) { if ( /\bmy\(([^\)]+)/ ) { foreach my $name (split(/,/,$1)) { push @{$vardecs{$name}}, $lineno; } } elsif ( /\bmy\s+([\%\$\*\@]\S+)/ ) { push @{$vardecs{$1}}, $lineno; my $nxt = 0; } $_ = substr( $_, $nxt+3 ); } } close DP; # Now do some reporting die "No lexically-scoped variables in $file\n" unless ( keys %vardecs +); my $nlisted = 0; foreach (sort keys %vardecs) { next unless ( scalar @{$vardecs{$_}} > 1 or $listyp eq ''); print join( ' ', $_, @{$vardecs{$_}}, "\n" ); $nlisted++; } print "\nTotal of $nlisted 'my' variables declared$listyp in $file\n"; print "(see $file.deparse for correct line-number references)\n" if ( $nlisted );
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Check a perl script for repeat "my" declarations
by robartes (Priest) on Apr 01, 2003 at 09:40 UTC | |
by Aristotle (Chancellor) on Apr 02, 2003 at 21:31 UTC | |
Re: Check a perl script for repeat "my" declarations
by awkmonk (Monk) on Apr 01, 2003 at 09:19 UTC |
Back to
Cool Uses for Perl