#!/usr/bin/perl -w use strict; # Walk through a perl script and look for 'naughty match variables' # $`, $&, and $', which may cause poor performance. # # usage: # find_naughty file1 [file2 [...]] # find_naughty $source, ); } ##################################################################### # # The PerlTokenSearch package is an interface to perltidy which accepts a # source filehandle and looks for selected variables. # # It works by making a callback object with a write_line() method to # receive tokenized lines from perltidy. # # Usage: # # PerlTokenSearch::find_naughty( # _source => $fh, # required source # ); # # _source is any source that perltidy will accept, including a # filehandle or reference to SCALAR or ARRAY # ##################################################################### package PerlTokenSearch; use Carp; use Perl::Tidy; sub find_naughty { my %args = ( @_ ); print "Testing File: $args{_source}\n"; # run perltidy, which will call $formatter's write_line() for each line my $err=perltidy( 'source' => $args{_source}, 'formatter' => bless( \%args, __PACKAGE__ ), # callback object 'argv' => "-npro -se", # -npro : ignore .perltidyrc, # -se : errors to STDOUT ); if ($err) { die "Error calling perltidy\n"; } } sub write_line { # This is called back from perltidy line-by-line # We're looking for $`, $&, and $' my ( $self, $line_of_tokens ) = @_; my $source = $self->{_source}; # pull out some stuff we might need my $line_type = $line_of_tokens->{_line_type}; my $input_line_number = $line_of_tokens->{_line_number}; my $input_line = $line_of_tokens->{_line_text}; my $rtoken_type = $line_of_tokens->{_rtoken_type}; my $rtokens = $line_of_tokens->{_rtokens}; chomp $input_line; # skip comments, pod, etc return if ( $line_type ne 'CODE' ); # loop over tokens looking for $`, $&, and $' for ( my $j = 0 ; $j < @$rtoken_type ; $j++ ) { # we only want to examine token types 'i' (identifier) next unless $$rtoken_type[$j] eq 'i'; # pull out the actual token text my $token = $$rtokens[$j]; # and check it if ( $token =~ /^\$[\`\&\']$/ ) { print STDERR "$source:$input_line_number: $token\n"; } } } # optional routine, called once after the last line of a file sub finish_formatting { my $self = shift; return; }