Perl::Critic::Policy::Modules::RequireExplicitInclusion(3pm)

NAME
Perl::Critic::Policy::Modules::RequireExplicitInclusion

AFFILIATION
This policy is part of Perl::Critic::StricterSubs.

DESCRIPTION
Checks that, if a reference is made to something inside of another package, that a module with the name of the package has been "use"d or "require"d.

Without importing a package, it is unlikely that references to things inside it even exist. Due to the flexible nature of Perl, "use strict;" can not complain about references to things outside of the current package and thus won't detect this situation.

  Explanation
As an example, assume there is a third-party "Foo" module with a bar() subroutine. You then create a module of your own.

  package My::Module;

  ...
  $x = Foo::bar($y);
  ...

You don't have to worry about whether "Foo" exports bar() or not because you're fully qualifying the name. Or do you? You then create a program plugh that uses your module that also needs to use "Foo" directly.

  #!/usr/bin/perl
  ...
  use Foo;
  use My::Module qw{ &frob };
  ...

This works fine. At some later time, you use your module in a xyzzy program.

  #!/usr/bin/perl
  ...
  use My::Module qw{ &frob };
  ...

You now get compilation problems in the previously robust "My::Module". What is going on is that plugh loaded the "Foo" module prior to "My::Module", which means that, when "My::Module" refers to Foo::bar(), the subroutine actually exists, even though "My::Module" didn't actually "use Foo;". When xyzzy attempted to use "My::Module" without doing a "use Foo;", "My::Module" fails because Foo::bar() doesn't exist.

  Enforcement
Assuming that there are no "use" or "require" statements within the current scope:

  @foo       = localtime;                        #ok
  @Bar::foo  = localtime                         #not ok
  @::foo     = localtime;                        #ok
  @main::foo = localtime;                        #ok

  baz(23, 'something', $x);                      #ok
  Bar::baz(23, 'something', $x);                 #not ok
  ::baz(23, 'something', $x);                    #ok
  main::baz(23, 'something', $x);                #ok

Only modules that are symbolically referenced by a "use" or "require" are considered valid. Loading a file does not count.

  use Foo;
  require Bar;
  require 'Baz.pm';

  $Foo:x = 57;                                   #ok
  $Bar:x = 57;                                   #ok
  $Baz:x = 57;                                   #not ok

Qualifying a name with the name of the current package is valid.

  package Xyzzy;

  my $ducks;

  sub increment_duck_count {
      $Xyzzy::ducks++;                           #ok
  }

A "use" or "require" statement is taken into account only when it is in the scope of a file or a "BEGIN", "CHECK", or "INIT" block.

  use File::Scope;

  BEGIN {
      require Begin::Block;
  }

  CHECK {
      require Check::Block;
  }

  INIT {
      require Init::Block;
  }

  END {
      require End::Block;
  }

  push @File::Scope::numbers, 52, 93, 25;        #ok
  push @Begin::Block::numbers, 52, 93, 25;       #ok
  push @Check::Block::numbers, 52, 93, 25;       #ok
  push @Init::Block::numbers, 52, 93, 25;        #ok
  push @End::Block::numbers, 52, 93, 25;         #not ok

  {
      require Lexical::Block;

      push @Lexical::Block::numbers, 52, 93, 25; #not ok
  }

CONFIGURATION
You can configure a list of modules that should be ignored by this policy. For example, it's common to use Test::Builder's variables in functions built on Test::More.

    use Test::More

    sub test_something {
        local $Test::Builder::Level = $Test::Builder::Level + 1;

        return is( ... );
    }

Using Test::More also brings in Test::Builder, so you don't need to do a call to "use". Unfortunately that trips this policy.

So to ignore violations on Test::Builder, you can add to your perlcriticrc file this section:

    [Modules::RequireExplicitInclusion]
    ignore_modules = Test::Builder

The "ignore_modules" argument can take a space-delimited list of modules, or of regexes, or both.

    [Modules::RequireExplicitInclusion]
    ignore_modules = Test::Builder /MooseX::/

CAVEATS
1.) It is assumed that the code for a package exists in a module of the same name.

2.) It is assumed that a module will contain no more than one package. This Policy will not complain about any problems in a module containing multiple "package" statements. For example, a module containing

  package Foo;

  sub frob {
      $Xyzzy::factor = rand 100;
  }

  package Bar;

  sub frob {
      $Plugh::factor = rand 1000;
  }

will not result in any violations. There really shouldn't be more than one package within a module anyway.

3.) No checks of whether the name actually exists in the referenced package are done. E.g., if a call to a Foo::process_widgets() subroutine is made, this Policy does not check that a process_widgets() subroutine actually exists in the "Foo" package.

DIAGNOSTICS

"Modules::RequireExplicitInclusion: Cannot cope with multiple packages in file"
    This warning happens when the file under analysis contains multiple packages, which is not currently supported. This Policy will simply ignore any file with multiple packages.

    Perl::Critic advises putting multiple packages in one file, and has additional Policies to help enforce that.

SEE ALSO
Perl::Critic::Policy::Modules::ProhibitMultiplePackages

AUTHOR
Jeffrey Ryan Thalhammer <thaljef@cpan.org>

COPYRIGHT
Copyright 2007-2024 Jeffrey Ryan Thalhammer and Andy Lester

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. The full text of this license can be found in the LICENSE file included with this module.