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

NAME

Dist::Zilla::Plugin::ExplicitPackageForClass - Insert an explicit package statement for class declarations

VERSION

version 1.00

SYNOPSIS

dist.ini:

  version = v1.23
  [ExplicitPackageForClass]

Perl module source file in the working directory, with an empty line before class:

  ...
  
  class Some::Module;

Resulting module file in the built distribution, with a package NAMESPACE VERSION statement inserted:

  ...
  package Some::Module v1.23;
  class Some::Module;

DESCRIPTION

During the build, this FileMunger plugin for Dist::Zilla will look through your code for class and role declarations and insert a corresponding package statement before them, along with the package version.

If you've tried the perlclass feature (also known as "Corinna") introduced with Perl v5.38, you may have run into problems with the toolchain. Corinna defines new keywords such as class that can replace keywords like package in modern code. Unfortunately, as of 2023, many tools used by developers to process Perl module distributions don't expect that Perl namespaces are declared by any other keyword than package. Even Dist::Zilla itself is affected, as is PPI, which is used by a number of Dist::Zilla plugins, leading to the possibility of error messages like these for files that declare namespaces with class:

  [PkgVersion] skipping lib/Foo/Bar.pm: no package statement found
  [MetaProvides::Package] No namespaces detected in file lib/Foo/Baz.pm
  ... and so on

"File Layout" in Object::Pad suggests that the class declaration should be preceded by a package statement until toolchain modules catch up. But manually duplicating the package name not only looks ugly, it's also a chore and a possible source of bugs. That's why this plugin will insert a package statement for you automatically before every class / role declaration.

The insertion only happens in the built distribution. The Perl source files in your working directory will never be touched by this plugin.

To ensure that line numbers won't change, it's required that the line before the class declaration is empty in your source file. The empty line will be replaced with a package NAMESPACE VERSION statement by this plugin. Because that already includes the module version, use of the PkgVersion plugin alongside this plugin should be avoided (or at least, custom file finders should be used to avoid that both of them work on the same files).

This plugin will only work on declarations where the class / role keyword is the first non-whitespace part of a line and is immediately followed by the namespace. However, it can't distinguish between Perl code on the one hand and heredocs / pod / data sections on the other. If valid class declarations exist outside the code, this plugin may erroneously try to insert a package declaration where it perhaps shouldn't.

This plugin is a stopgap that will hopefully become redundant as the new experimental class feature stabilises and more parts of Perl's toolchain add support for it.

ATTRIBUTES

finder

  [FileFinder::Filter / ModulesExceptFoo]
  finder = :InstallModules
  skip = Foo\.pm
  
  [ExplicitPackageForClass]
  finder = ModulesExceptFoo

The name of a FileFinder for assembling the list of modules to work on. Defaults to just :InstallModules. May be given multiple times.

SEE ALSO

"File Layout" in Object::Pad

AUTHOR

Arne Johannessen (AJNN)

COPYRIGHT AND LICENSE

This software is Copyright (c) 2023 by Arne Johannessen.

This is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0 or (at your option) the same terms as the Perl 5 programming language system itself.