The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

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 used or required.

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
  }

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.

CONFIGURATION

None.

DIAGNOSTICS

Modules::RequireExplicitInclusion: Cannot cope with mutiple 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 (c) 2007 Jeffrey Ryan Thalhammer. All rights reserved.

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.