no longer just digit has asked for the wisdom of the Perl Monks concerning the following question:

Today, doing some module renaming work, I found that I had "use <Module>" in a lot of files where it was not being used. I expected to find a CPAN solution for finding unused "use Module" statements but the best I got was this old stackoverflow answer:

I already know Test::Vars for removing unused variables, but is there a good Test::Modules or similar for detecting unused modules included into files?

Replies are listed 'Best First'.
Re: Removing unused Perl modules
by Corion (Pope) on Apr 22, 2021 at 07:24 UTC

    I have such a test in my Perl distribution template.

    The test is a (not so) simple glue of Perl::PrereqScanner::Lite to find all used modules and some other stuff to remove known modules, and it (re)runs the test suite with each module blocked in turn.

    This test basically works, except for the cases where I dynamically use different modules based (for example) on the operating system or other things that the test suite will not pick up on, because it (for exmample) only runs on Linux while a module is dynamically required on Windows.

Re: Removing unused Perl modules
by bliako (Prior) on Apr 22, 2021 at 07:33 UTC

    Module::Used, Module::ScanDeps, Module::Extract::Use et al., Devel::TraceUse can all be useful in listing what modules you instructed perl to use (as opposed to what modules are "usefully used" which is what you want).

    I assume the difficult bit will be to find a way to remove each of these modules from source in order to see the effect on compilation (as you suggested in a comment below). Removing from source code (e.g. with regex) can be trickier than finding them. Because finding them usually involves reading the %INC and I am not sure whether removing from %INC will have any effect at all.

    One thing that comes to my mind, totally untested, is: instead of removing a module from source code and run, just prepend a dir in @INC which will contain "fake" module files (with empty content, bar the boilerplate). For example:

    mkdir -p fakemodules/Data echo "package Data::Dumper;1;" > fakemodules/Data/ # this will fail: perl -Ifakemodules -MData::Dumper -e'print Data::Dumper::Dumper([1])' a=$? # this succeeds: perl -MData::Dumper -e'print Data::Dumper::Dumper([1])' b=$? if [ $a -ne 0 ] && [ $b -eq 0 ]; then echo "module is required"; fi

    1 minute edit: I think choroba mentioned a similar technique for mocking modules and probably this is where I got it from

    bw, bliako

Re: Removing unused Perl modules
by perlfan (Vicar) on Apr 22, 2021 at 05:14 UTC
    Not even you can determine if something from one of those modules is used without careful inspection (which amounts to running the code in your mind) or running the code, carefully probing for breakage. You will need to reason through all of your code to determine if you need a module or not. A good way to cheat is to avoid any exports via use MODULE::NAME (); You are asking to do something that could potentially be undecidable.
        That sounds very reasonable.
Re: Removing unused Perl modules
by no longer just digit (Beadle) on May 07, 2021 at 01:22 UTC

    Self update: I've just seen App::perlimports mentioned on reddit, this might help. It seems to not actually detect unused modules by itself, but it adds a list of imports. So for example I found a script which has

    use Math::Trig;

    in it, but it doesn't actually use that, and App::perlimports changed that to

    use Math::Trig ();

    so I could tell it wasn't being used.