Thread: [Lxr-general] Finding unreferenced functions
Brought to you by:
ajlittoz
From: Michael O'C. <moc...@ya...> - 2005-01-06 15:25:57
|
Hi, Apologies if this has been asked before. I'm wondering if anyone's tried using lxr on a codebase to find unreferenced / unused functions. I tried this on a C / C++ codebase I've been working in and found it very useful as part of a clean-up exercise. It depends on relational database storage of the lxr data (mysql in my case). A query counting the number of instances of each symbol in the indexes table can be compared with an equivalent query on the useages table, where the latter count is <= the former the symbol can be considered unreferenced (i.e. not used). It's not foolproof, depends on indexing of all dependent code, and won't find all instances (due to the regex nature of lxr's symbol finding / storage), nonetheless I've found it an easy an quick way of finding unused code. I guess there are better ways of achieving the same result, I'd like to hear what people think. Thanks, Michael __________________________________ Do you Yahoo!? Yahoo! Mail - Find what you need with new enhanced search. http://info.mail.yahoo.com/mail_250 |
From: Tom S. <to...@pl...> - 2005-01-06 17:14:08
|
On Thu, 2005-01-06 at 07:25 -0800, Michael O'Connor wrote: > Hi, > > Apologies if this has been asked before. I'm wondering if anyone's tried using > lxr on a codebase to find unreferenced / unused functions. I tried this on a C > / C++ codebase I've been working in and found it very useful as part of a > clean-up exercise. Here is what I have done. I am not sure exactly what version of LXR I am running, here is the CVS Id from the ident script: # $Id: ident,v 1.6 1998/04/30 11:58:16 argggh Exp $ Here are some bits to add to Common.pm: sub uiref { my ($desc, $pr, @args) = @_; return("<a href=\"unref". &urlargs(($pr ? "pr=$pr" : ""), @args). "\"\>$desc</a>"); } This goes at the end of titleexpand: } elsif ($who eq 'unref') { return($Conf->sourcerootname.' unreferenced identifier search'); } This goes after the 'find' part in modeexpand: if ($who eq 'unref') { push(@mlist, "<b><i>unreferenced identifier search</i></b>"); } else { push(@mlist, &uiref("unreferenced identifier search", "")); } This goes after the 'find' part in varlinks: } elsif ($who eq 'unref') { $vallink = &uiref($val, $identifier, "$var=$val"); } ======================================================================== Here is my file called "unref". It is just a modification of the ident script, and it belongs in the same directory. #!/usr/bin/perl # unref -- Find unreferenced identifiers # # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ###################################################################### use lib 'lib/'; use LXR::Common; use LXR::Config; use DB_File; my $sort_by_identifier = 0; sub unref { print("<form method=get action=\"unref\">\n"); foreach ($Conf->allvariables) { if ($Conf->variable($_) ne $Conf->vardefault($_)) { print("<input type=hidden name=\"",$_, "\" ", "value=\"", $Conf->variable($_), "\">\n"); } } print( "Pathname regexp: <input type=text name=\"pr\" ", "value=\"",$pathname_regexp,"\" size=60>\n", "<input type=submit value=\"Go get it\">\n", "</form>\n" ); tie(%xref, "DB_File", $Conf->dbdir."/xref", O_RDONLY, 0644, $DB_HASH) || &fatal("Could not open \"".$Conf->dbdir."/xref\""); tie(%fileidx, "DB_File", $Conf->dbdir."/fileidx", O_RDONLY, 0644, $DB_HASH) || &fatal("Could not open \"".$Conf->dbdir."/fileidx\""); if ($pathname_regexp) { while (($identifier, $data) = each(%xref)) { # Ignore C++ destructors, because they are implicitly # referenced by delete() if ($identifier =~ /^~/) { next; } @refs = split(/\t/, $data); unless (@refs) { next; } @filtered_refs = grep(/^R/, @refs); if (int(@filtered_refs) > 2) { next; } foreach (@filtered_refs) { if (/^R(.+):([\d,]+)/) { $fnam = $fileidx{$1}; @fpos = split(/,/, $2); unless ($fnam =~ /$pathname_regexp/) { next; } # ignore definitions in .h files if ($fnam =~ /\.h$|\._h$/) { next; } if ($#fpos == 0) { if ($sort_by_identifier) { $unref_ident{$identifier} = &fileref( "$fnam, line $fpos[0]", "/$fnam", $fpos[0] ); } else { $unref_ident{ &fileref( "$fnam, line $fpos[0]", "/$fnam", $fpos[0] ) } = $identifier; } } } } } untie(%fileidx); untie(%xref); @keylist = keys(%unref_ident); print("<h1>Unreferenced identifiers (", $#keylist, ")</h1>\n"); print("<table>\n"); if ($sort_by_identifier) { print("<tr><th>Identifier</th><th>File</th></tr>\n"); foreach $identifier (sort(@keylist)) { print( "<tr><td>", &idref($identifier, $identifier), "</td><td>", $unref_ident{$identifier}, "</td></tr>\n" ); } } else { print("<tr><th>File</th><th>Identifier</th></tr>\n"); foreach $fref (sort(@keylist)) { print( "<tr><td>", $fref, "</td><td>", &idref($unref_ident{$fref}, $unref_ident{$fref}), "</td></tr>\n" ); } } print("</table>\n"); } else { print( "<p>You must specify a pathname regexp.", " Use '.' to match all files." ); } } ($Conf, $HTTP, $Path) = &init; $pathname_regexp = $HTTP->{'param'}->{'pr'}; &makeheader('unref'); &unref; &makefooter('unref'); |
From: Malcolm B. <ma...@br...> - 2005-01-08 17:54:42
|
Michael O'Connor wrote: > Hi, > > Apologies if this has been asked before. I'm wondering if anyone's tried using > lxr on a codebase to find unreferenced / unused functions. I tried this on a C > / C++ codebase I've been working in and found it very useful as part of a > clean-up exercise. I haven't heard of anyone doing this - sounds like a good idea, and a possibly useful extension to LXR. <snip description of method> > I guess there are better ways of achieving the same result, I'd like to hear > what people think. Might be, but I can't think of one off the top of my head. If you could send me the SQL you were using I can look to see if it can be built into LXR in some way - perhaps by adding a "find unused symbols" search, or by showing unused symbols in the ident search? Cheers, Malcolm |
From: Michael O'C. <moc...@ya...> - 2005-01-11 13:07:02
|
Here goes: 1st query ('indexes_count'): select i2.symid, count(*) from ${prefix}files f, ${prefix}indexes i1, ${prefix}indexes i2 where f.filename like ? and f.fileid = i1.fileid and i2.symid = i1.symid group by i2.symid 2nd query ('usages_count'): select u.symid, count(*) from ${prefix}files f, ${prefix}indexes i, ${prefix}useage u where f.filename like ? and f.fileid = i.fileid and u.symid = i.symid group by u.symid The bind variable in both cases is a source-code tree path (e.g. '/src/c/api/%'), this is in order to limit the hit on the database. I also added an abort before performing the 2nd query if the no. of results from the 1st query is too large for the same reason (I used a limit of 10000). I guess a join to the releases table is also needed (I'm only storing one release so I got away without it). Simultaneous iteration through the results of the 2 queries (stored in separate perl hashes as symbol => no. of occurrances) allows a check for symbols that are not referenced other than where they're declared or defined. Michael --- Malcolm Box <ma...@br...> wrote: > Michael O'Connor wrote: > > Hi, > > > > Apologies if this has been asked before. I'm wondering if anyone's tried > using > > lxr on a codebase to find unreferenced / unused functions. I tried this on > a C > > / C++ codebase I've been working in and found it very useful as part of a > > clean-up exercise. > > I haven't heard of anyone doing this - sounds like a good idea, and a > possibly useful extension to LXR. > > <snip description of method> > > > I guess there are better ways of achieving the same result, I'd like to > hear > > what people think. > > Might be, but I can't think of one off the top of my head. If you could > send me the SQL you were using I can look to see if it can be built into > LXR in some way - perhaps by adding a "find unused symbols" search, or > by showing unused symbols in the ident search? > > Cheers, > > Malcolm > __________________________________ Do you Yahoo!? Meet the all-new My Yahoo! - Try it today! http://my.yahoo.com |