Perl-Critic-Community-v1.0.4000755001750001750 014734076151 16012 5ustar00grinnzgrinnz000000000000README100644001750001750 1056714734076151 17004 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4NAME Perl::Critic::Community - Community-inspired Perl::Critic policies SYNOPSIS $ perlcritic --theme community script.pl $ perlcritic --theme community lib/ # .perlcriticrc theme = community severity = 1 DESCRIPTION A set of Perl::Critic policies to enforce the practices generally recommended by subsets of the Perl community, particularly on IRC. Formerly known as Perl::Critic::Freenode. Because this policy "theme" is designed to be used with zero configuration on the command line, some duplication will occur if it is used in combination with core Perl::Critic policies. AFFILIATION This module has no functionality, but instead contains documentation for this distribution and acts as a means of pulling other modules into a bundle. All of the Policy modules contained herein will have an "AFFILIATION" section announcing their participation in this grouping. POLICIES Perl::Critic::Policy::Community::AmpersandSubCalls Don't use & to call subroutines Perl::Critic::Policy::Community::ArrayAssignAref Don't assign an anonymous arrayref to an array Perl::Critic::Policy::Community::BarewordFilehandles Don't use bareword filehandles other than built-ins Perl::Critic::Policy::Community::ConditionalDeclarations Don't declare variables conditionally Perl::Critic::Policy::Community::ConditionalImplicitReturn Don't end a subroutine with a conditional block Perl::Critic::Policy::Community::DeprecatedFeatures Avoid features that have been deprecated or removed from Perl Perl::Critic::Policy::Community::DiscouragedModules Various modules discouraged from use Perl::Critic::Policy::Community::DollarAB Don't use $a or $b as variable names outside sort() Perl::Critic::Policy::Community::Each Don't use each() to iterate through a hash Perl::Critic::Policy::Community::EmptyReturn Don't use return with no arguments Perl::Critic::Policy::Community::IndirectObjectNotation Don't call methods indirectly Perl::Critic::Policy::Community::LexicalForeachIterator Don't use undeclared foreach loop iterators Perl::Critic::Policy::Community::LoopOnHash Don't loop over hashes Perl::Critic::Policy::Community::ModPerl Don't use mod_perl to write web applications Perl::Critic::Policy::Community::MultidimensionalArrayEmulation Don't use multidimensional array emulation Perl::Critic::Policy::Community::OpenArgs Always use the three-argument form of open() Perl::Critic::Policy::Community::OverloadOptions Don't use overload without specifying a bool overload and enabling fallback Perl::Critic::Policy::Community::PackageMatchesFilename Module files should declare a package matching the filename Perl::Critic::Policy::Community::POSIXImports Don't use POSIX without specifying an import list Perl::Critic::Policy::Community::PreferredAlternatives Various modules with preferred alternatives Perl::Critic::Policy::Community::Prototypes Don't use function prototypes Perl::Critic::Policy::Community::SplitQuotedPattern Quote the split() pattern argument with regex slashes Perl::Critic::Policy::Community::StrictWarnings Always use strict and warnings, or a module that imports these Perl::Critic::Policy::Community::Threads Interpreter-based threads are officially discouraged Perl::Critic::Policy::Community::Wantarray Don't write context-sensitive functions using wantarray() Perl::Critic::Policy::Community::WarningsSwitch Scripts should not use the -w switch on the shebang line Perl::Critic::Policy::Community::WhileDiamondDefaultAssignment Don't use while with implicit assignment to $_ CONFIGURATION AND ENVIRONMENT All policies included are in the "community" theme. See the Perl::Critic documentation for how to make use of this. AUTHOR Dan Book, dbook@cpan.org CONTRIBUTORS Graham Knop (haarg) H.Merijn Brand (Tux) John SJ Anderson (genehack) Matt S Trout (mst) William Taylor (willt) COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. SEE ALSO Perl::Critic Changes100644001750001750 1347514734076151 17420 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4v1.0.4 2024-12-28 17:32:08 EST - Add SplitQuotedPattern policy - Mention 'indirect' and 'multidimensional' features in the appropriate documentation - Replace dependency on Perl::Critic::Pulp with Plicease::ProhibitArrayAssignAref (plicease #55) - Remove Freenode legacy aliases from new versions of the distribution as they will no longer be updated v1.0.3 2022-07-24 02:27:25 EDT - Allow use v5.36+ to satisfy StrictWarnings policy (marlencrabapple #50) - Recognize use v5.36+ in the Prototypes policy as an indication that signatures are enabled v1.0.2 2021-12-23 16:08:00 EST - Add IP::World to DiscouragedModules policy (DrHyde #46) v1.0.1 2021-10-21 14:17:55 EDT - Support configuring allowed_modules for DiscouragedModules and PreferredAlternatives policies (Amorymeltzer #43) v1.0.0 2021-05-27 02:44:33 EDT - Rename to Perl::Critic::Community and move policies to the 'community' theme (Freenode modules and theme remain as legacy aliases) 0.033 2020-12-21 19:39:58 EST - Update various recommendations for alternatives in DiscouragedModules policy - Add better examples for EmptyReturn (#39) and Each policies 0.032 2019-11-11 11:09:08 EST - Add check for CORE::wantarray and CORE'wantarray to WantArray policy (simcop2387 #37) 0.031 2019-09-25 19:00:39 EDT - Add FindBin to DiscouragedModules policy (#31) - Add MultidimensionalArrayEmulation policy (#35) 0.030 2019-08-26 11:27:15 EDT - Allow signature_enablers to be configured for Prototypes policy (#34) 0.029 2019-04-26 13:12:43 EDT - Added LexicalForeachIterator policy - Require PPI 1.252+ allowing simplifications to the DeprecatedFeatures and WhileDiamondDefaultAssignment policies 0.028 2018-11-29 19:32:49 EST - Split out lower severity violations from DiscouragedModules policy into a new PreferredAlternatives policy. Perl::Critic does not support filtering individual violations by severity, only policies, so this will allow separately configuring and filtering these violations. - Fixed DiscouragedModules and DeprecatedFeatures policy violations to report severity as configured. - Fixed DeprecatedFeatures to avoid false positives on method calls with the same name as autoderef functions. - Added /\C/, chdir(''), and bare here-docs to DeprecatedFeatures policy. 0.027 2018-06-20 20:17:06 EDT - Add LoopOnHash policy 0.026 2018-02-16 20:50:14 EST - Update Prototypes policy to recognize more ways of activating the signatures feature 0.025 2018-02-11 01:31:58 EST - Fix DeprecatedFeatures to recognize correctly-parsed postderef in PPI 1.237+ - Avoid warning from running PackageMatchesFilename policy on a document without a filename (willt #29) - Fix another false positive in DollarAB policy 0.024 2017-08-16 22:39:53 EDT - Make PackageMatchesFilename more robust against infinite loops 0.023 2017-08-16 22:22:40 EDT - Fix issue where PackageMatchesFilename policy would loop infinitely 0.022 2017-08-16 22:17:38 EDT - Also consider -W a violation of WarningsSwitch policy - Fix false positive in DollarAB policy where $a or $b is within another block - Add PackageMatchesFilename policy 0.021 2017-06-03 19:49:16 EDT - Be more lenient when trying to detect postderef for DeprecatedFeatures autoderef violations 0.020 2017-05-15 20:45:02 EDT - Updates to documentation for DeprecatedFeatures and DiscouragedModules policies - Add require ::Foo::Bar to DeprecatedFeatures policy - Remove qr//xx from DeprecatedFeatures policy as this is now a valid regex modifier in 5.26. 0.019 2017-01-29 22:13:34 EST - Add autoderef to DeprecatedFeatures policy 0.018 2016-12-08 21:32:40 EST - Add IndirectObjectNotation policy 0.017 2016-09-29 17:24:15 EDT - DeprecatedFeatures will now consider "use UNIVERSAL;" a policy violation - Add OverloadOptions policy 0.016 2016-07-02 17:53:20 EDT - Support <<>> operator in WhileDiamondDefaultAssignment policy - Fixes for DeprecatedFeatures checking of /xx violations 0.015 2016-07-02 03:20:35 EDT - add ArrayAssignAref policy - update DeprecatedFeatures policy with features deprecated in 5.22 and to be removed in 5.26 0.014 2016-01-26 20:45:18 EST - allow pairwise in DollarAB policy - allow DollarAB pair functions to be extended 0.013 2015-12-17 18:07:03 EST - Add ConditionalDeclarations policy 0.012 2015-10-16 15:13:21 EDT - add IO::Socket::INET6 to discouraged modules - Fix EmptyReturn to avoid reporting violations in void context functions - Add POSIXImports policy - Add ConditionalImplicitReturn policy 0.011 2015-09-15 13:32:44 EDT - add Getopt::Std to discouraged modules - Fix EmptyReturn to catch more cases - Add DeprecatedFeatures policy 0.010 2015-08-28 17:11:40 EDT - Fix Changes - Change installer to Module::Build::Tiny 0.009 2015-08-27 15:09:22 EDT - Add Class::DBI, Error.pm, and Readonly.pm to discouraged modules 0.008 2015-08-25 21:42:10 EDT - Various documentation updates - Add Switch.pm to discouraged modules 0.007 2015-08-15 17:18:23 EDT - fix StrictWarnings parsing of "use VERSION" (Tux) - handle readline/readdir/each in WhileDiamondDefaultAssignment 0.006 2015-07-30 22:34:15 EDT - just use core policy for AmpersandSubCalls - add clarification for policies that are similar to core policies 0.005 2015-07-13 10:49:45 EDT - fix false positives in DollarAB policy 0.004 2015-07-01 17:21:16 EDT - use default strict/warnings importers from Perl::Critic::Utils::Constants 0.003 2015-06-27 17:53:00 EDT - allow prototypes containing & - add Each polciy - make StrictWarnings policy configurable with extra importers 0.002 2015-06-27 00:07:19 EDT - add AmpersandSubCalls policy - add policy abstracts 0.001 2015-06-26 21:01:32 EDT - First release LICENSE100644001750001750 2151514734076151 17124 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4This software is Copyright (c) 2015 by Dan Book. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) The Artistic License 2.0 Copyright (c) 2000-2006, The Perl Foundation. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble This license establishes the terms under which a given free software Package may be copied, modified, distributed, and/or redistributed. The intent is that the Copyright Holder maintains some artistic control over the development of that Package while still keeping the Package available as open source and free software. You are always permitted to make arrangements wholly outside of this license directly with the Copyright Holder of a given Package. If the terms of this license do not permit the full use that you propose to make of the Package, you should contact the Copyright Holder and seek a different licensing arrangement. Definitions "Copyright Holder" means the individual(s) or organization(s) named in the copyright notice for the entire Package. "Contributor" means any party that has contributed code or other material to the Package, in accordance with the Copyright Holder's procedures. "You" and "your" means any person who would like to copy, distribute, or modify the Package. "Package" means the collection of files distributed by the Copyright Holder, and derivatives of that collection and/or of those files. A given Package may consist of either the Standard Version, or a Modified Version. "Distribute" means providing a copy of the Package or making it accessible to anyone else, or in the case of a company or organization, to others outside of your company or organization. "Distributor Fee" means any fee that you charge for Distributing this Package or providing support for this Package to another party. It does not mean licensing fees. "Standard Version" refers to the Package if it has not been modified, or has been modified only in ways explicitly requested by the Copyright Holder. "Modified Version" means the Package, if it has been changed, and such changes were not explicitly requested by the Copyright Holder. "Original License" means this Artistic License as Distributed with the Standard Version of the Package, in its current version or as it may be modified by The Perl Foundation in the future. "Source" form means the source code, documentation source, and configuration files for the Package. "Compiled" form means the compiled bytecode, object code, binary, or any other form resulting from mechanical transformation or translation of the Source form. Permission for Use and Modification Without Distribution (1) You are permitted to use the Standard Version and create and use Modified Versions for any purpose without restriction, provided that you do not Distribute the Modified Version. Permissions for Redistribution of the Standard Version (2) You may Distribute verbatim copies of the Source form of the Standard Version of this Package in any medium without restriction, either gratis or for a Distributor Fee, provided that you duplicate all of the original copyright notices and associated disclaimers. At your discretion, such verbatim copies may or may not include a Compiled form of the Package. (3) You may apply any bug fixes, portability changes, and other modifications made available from the Copyright Holder. The resulting Package will still be considered the Standard Version, and as such will be subject to the Original License. Distribution of Modified Versions of the Package as Source (4) You may Distribute your Modified Version as Source (either gratis or for a Distributor Fee, and with or without a Compiled form of the Modified Version) provided that you clearly document how it differs from the Standard Version, including, but not limited to, documenting any non-standard features, executables, or modules, and provided that you do at least ONE of the following: (a) make the Modified Version available to the Copyright Holder of the Standard Version, under the Original License, so that the Copyright Holder may include your modifications in the Standard Version. (b) ensure that installation of your Modified Version does not prevent the user installing or running the Standard Version. In addition, the Modified Version must bear a name that is different from the name of the Standard Version. (c) allow anyone who receives a copy of the Modified Version to make the Source form of the Modified Version available to others under (i) the Original License or (ii) a license that permits the licensee to freely copy, modify and redistribute the Modified Version using the same licensing terms that apply to the copy that the licensee received, and requires that the Source form of the Modified Version, and of any works derived from it, be made freely available in that license fees are prohibited but Distributor Fees are allowed. Distribution of Compiled Forms of the Standard Version or Modified Versions without the Source (5) You may Distribute Compiled forms of the Standard Version without the Source, provided that you include complete instructions on how to get the Source of the Standard Version. Such instructions must be valid at the time of your distribution. If these instructions, at any time while you are carrying out such distribution, become invalid, you must provide new instructions on demand or cease further distribution. If you provide valid instructions or cease distribution within thirty days after you become aware that the instructions are invalid, then you do not forfeit any of your rights under this license. (6) You may Distribute a Modified Version in Compiled form without the Source, provided that you comply with Section 4 with respect to the Source of the Modified Version. Aggregating or Linking the Package (7) You may aggregate the Package (either the Standard Version or Modified Version) with other packages and Distribute the resulting aggregation provided that you do not charge a licensing fee for the Package. Distributor Fees are permitted, and licensing fees for other components in the aggregation are permitted. The terms of this license apply to the use and Distribution of the Standard or Modified Versions as included in the aggregation. (8) You are permitted to link Modified and Standard Versions with other works, to embed the Package in a larger work of your own, or to build stand-alone binary or bytecode versions of applications that include the Package, and Distribute the result without restriction, provided the result does not expose a direct interface to the Package. Items That are Not Considered Part of a Modified Version (9) Works (including, but not limited to, modules and scripts) that merely extend or make use of the Package, do not, by themselves, cause the Package to be a Modified Version. In addition, such works are not considered parts of the Package itself, and are not subject to the terms of this license. General Provisions (10) Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license. (11) If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license. (12) This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder. (13) This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed. (14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. INSTALL100644001750001750 473514734076151 17135 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4This is the Perl distribution Perl-Critic-Community. Installing Perl-Critic-Community is straightforward. ## Installation with cpanm If you have cpanm, you only need one line: % cpanm Perl::Critic::Community If it does not have permission to install modules to the current perl, cpanm will automatically set up and install to a local::lib in your home directory. See the local::lib documentation (https://metacpan.org/pod/local::lib) for details on enabling it in your environment. ## Installing with the CPAN shell Alternatively, if your CPAN shell is set up, you should just be able to do: % cpan Perl::Critic::Community ## Manual installation As a last resort, you can manually install it. If you have not already downloaded the release tarball, you can find the download link on the module's MetaCPAN page: https://metacpan.org/pod/Perl::Critic::Community Untar the tarball, install configure prerequisites (see below), then build it: % perl Build.PL % ./Build && ./Build test Then install it: % ./Build install Or the more portable variation: % perl Build.PL % perl Build % perl Build test % perl Build install If your perl is system-managed, you can create a local::lib in your home directory to install modules to. For details, see the local::lib documentation: https://metacpan.org/pod/local::lib The prerequisites of this distribution will also have to be installed manually. The prerequisites are listed in one of the files: `MYMETA.yml` or `MYMETA.json` generated by running the manual build process described above. ## Configure Prerequisites This distribution requires other modules to be installed before this distribution's installer can be run. They can be found under the "configure_requires" key of META.yml or the "{prereqs}{configure}{requires}" key of META.json. ## Other Prerequisites This distribution may require additional modules to be installed after running Build.PL. Look for prerequisites in the following phases: * to run ./Build, PHASE = build * to use the module code itself, PHASE = runtime * to run tests, PHASE = test They can all be found in the "PHASE_requires" key of MYMETA.yml or the "{prereqs}{PHASE}{requires}" key of MYMETA.json. ## Documentation Perl-Critic-Community documentation is available as POD. You can run `perldoc` from a shell to read the documentation: % perldoc Perl::Critic::Community For more information on installing Perl modules via CPAN, please see: https://www.cpan.org/modules/INSTALL.html dist.ini100644001750001750 53114734076151 17516 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4name = Perl-Critic-Community author = Dan Book license = Artistic_2_0 copyright_holder = Dan Book copyright_year = 2015 [@Author::DBOOK] :version = v1.0.2 installer = ModuleBuildTiny::Fallback irc = irc://irc.libera.chat/#perl pod_tests = syntax Test::ReportPrereqs.include[] = PPI [lib] lib = lib [Test::Perl::Critic] META.yml100644001750001750 1342114734076151 17365 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4--- abstract: 'Community-inspired Perl::Critic policies' author: - 'Dan Book ' build_requires: File::Spec: '0' Module::Metadata: '0' Test::More: '0' configure_requires: Module::Build::Tiny: '0.034' dynamic_config: 0 generated_by: 'Dist::Zilla version 6.032, CPAN::Meta::Converter version 2.150010' license: artistic_2 meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Perl-Critic-Community no_index: directory: - eg - examples - inc - share - t - xt provides: Perl::Critic::Community: file: lib/Perl/Critic/Community.pm version: v1.0.4 Perl::Critic::Community::Utils: file: lib/Perl/Critic/Community/Utils.pm version: v1.0.4 Perl::Critic::Policy::Community::AmpersandSubCalls: file: lib/Perl/Critic/Policy/Community/AmpersandSubCalls.pm version: v1.0.4 Perl::Critic::Policy::Community::ArrayAssignAref: file: lib/Perl/Critic/Policy/Community/ArrayAssignAref.pm version: v1.0.4 Perl::Critic::Policy::Community::BarewordFilehandles: file: lib/Perl/Critic/Policy/Community/BarewordFilehandles.pm version: v1.0.4 Perl::Critic::Policy::Community::ConditionalDeclarations: file: lib/Perl/Critic/Policy/Community/ConditionalDeclarations.pm version: v1.0.4 Perl::Critic::Policy::Community::ConditionalImplicitReturn: file: lib/Perl/Critic/Policy/Community/ConditionalImplicitReturn.pm version: v1.0.4 Perl::Critic::Policy::Community::DeprecatedFeatures: file: lib/Perl/Critic/Policy/Community/DeprecatedFeatures.pm version: v1.0.4 Perl::Critic::Policy::Community::DiscouragedModules: file: lib/Perl/Critic/Policy/Community/DiscouragedModules.pm version: v1.0.4 Perl::Critic::Policy::Community::DollarAB: file: lib/Perl/Critic/Policy/Community/DollarAB.pm version: v1.0.4 Perl::Critic::Policy::Community::Each: file: lib/Perl/Critic/Policy/Community/Each.pm version: v1.0.4 Perl::Critic::Policy::Community::EmptyReturn: file: lib/Perl/Critic/Policy/Community/EmptyReturn.pm version: v1.0.4 Perl::Critic::Policy::Community::IndirectObjectNotation: file: lib/Perl/Critic/Policy/Community/IndirectObjectNotation.pm version: v1.0.4 Perl::Critic::Policy::Community::LexicalForeachIterator: file: lib/Perl/Critic/Policy/Community/LexicalForeachIterator.pm version: v1.0.4 Perl::Critic::Policy::Community::LoopOnHash: file: lib/Perl/Critic/Policy/Community/LoopOnHash.pm version: v1.0.4 Perl::Critic::Policy::Community::ModPerl: file: lib/Perl/Critic/Policy/Community/ModPerl.pm version: v1.0.4 Perl::Critic::Policy::Community::MultidimensionalArrayEmulation: file: lib/Perl/Critic/Policy/Community/MultidimensionalArrayEmulation.pm version: v1.0.4 Perl::Critic::Policy::Community::OpenArgs: file: lib/Perl/Critic/Policy/Community/OpenArgs.pm version: v1.0.4 Perl::Critic::Policy::Community::OverloadOptions: file: lib/Perl/Critic/Policy/Community/OverloadOptions.pm version: v1.0.4 Perl::Critic::Policy::Community::POSIXImports: file: lib/Perl/Critic/Policy/Community/POSIXImports.pm version: v1.0.4 Perl::Critic::Policy::Community::PackageMatchesFilename: file: lib/Perl/Critic/Policy/Community/PackageMatchesFilename.pm version: v1.0.4 Perl::Critic::Policy::Community::PreferredAlternatives: file: lib/Perl/Critic/Policy/Community/PreferredAlternatives.pm version: v1.0.4 Perl::Critic::Policy::Community::Prototypes: file: lib/Perl/Critic/Policy/Community/Prototypes.pm version: v1.0.4 Perl::Critic::Policy::Community::SplitQuotedPattern: file: lib/Perl/Critic/Policy/Community/SplitQuotedPattern.pm version: v1.0.4 Perl::Critic::Policy::Community::StrictWarnings: file: lib/Perl/Critic/Policy/Community/StrictWarnings.pm version: v1.0.4 Perl::Critic::Policy::Community::Threads: file: lib/Perl/Critic/Policy/Community/Threads.pm version: v1.0.4 Perl::Critic::Policy::Community::Wantarray: file: lib/Perl/Critic/Policy/Community/Wantarray.pm version: v1.0.4 Perl::Critic::Policy::Community::WarningsSwitch: file: lib/Perl/Critic/Policy/Community/WarningsSwitch.pm version: v1.0.4 Perl::Critic::Policy::Community::WhileDiamondDefaultAssignment: file: lib/Perl/Critic/Policy/Community/WhileDiamondDefaultAssignment.pm version: v1.0.4 requires: Carp: '0' Exporter: '0' List::Util: '1.33' PPI: '1.254' Path::Tiny: '0.101' Perl::Critic: '1.126' Perl::Critic::Policy::Objects::ProhibitIndirectSyntax: '1.126' Perl::Critic::Policy::Plicease::ProhibitArrayAssignAref: '100.00' Perl::Critic::Policy::Subroutines::ProhibitAmpersandSigils: '1.126' Perl::Critic::Policy::Variables::ProhibitConditionalDeclarations: '1.126' Perl::Critic::Policy::Variables::ProhibitLoopOnHash: '0.005' Perl::Critic::Policy::Variables::RequireLexicalLoopIterators: '1.126' Scalar::Util: '0' parent: '0' perl: '5.010001' version: '0' resources: IRC: irc://irc.libera.chat/#perl bugtracker: https://github.com/Grinnz/Perl-Critic-Community/issues homepage: https://github.com/Grinnz/Perl-Critic-Community repository: https://github.com/Grinnz/Perl-Critic-Community.git version: v1.0.4 x_contributors: - 'Amory Meltzer ' - 'Dan Book ' - 'Dan Book ' - 'David Cantrell ' - 'Graham Knop ' - 'Graham Ollis ' - 'Ian Bradley ' - 'Karen Etheridge ' - 'Nicolas Rochelemagne ' - 'Ryan Voots ' - 'Tomasz Konojacki ' - 'William Taylor ' x_generated_by_perl: v5.40.0 x_serialization_backend: 'YAML::Tiny version 1.74' x_spdx_expression: Artistic-2.0 MANIFEST100644001750001750 516614734076151 17234 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4# This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.032. Build.PL CONTRIBUTING.md Changes INSTALL LICENSE MANIFEST META.json META.yml README dist.ini lib/Perl/Critic/Community.pm lib/Perl/Critic/Community/Utils.pm lib/Perl/Critic/Policy/Community/AmpersandSubCalls.pm lib/Perl/Critic/Policy/Community/ArrayAssignAref.pm lib/Perl/Critic/Policy/Community/BarewordFilehandles.pm lib/Perl/Critic/Policy/Community/ConditionalDeclarations.pm lib/Perl/Critic/Policy/Community/ConditionalImplicitReturn.pm lib/Perl/Critic/Policy/Community/DeprecatedFeatures.pm lib/Perl/Critic/Policy/Community/DiscouragedModules.pm lib/Perl/Critic/Policy/Community/DollarAB.pm lib/Perl/Critic/Policy/Community/Each.pm lib/Perl/Critic/Policy/Community/EmptyReturn.pm lib/Perl/Critic/Policy/Community/IndirectObjectNotation.pm lib/Perl/Critic/Policy/Community/LexicalForeachIterator.pm lib/Perl/Critic/Policy/Community/LoopOnHash.pm lib/Perl/Critic/Policy/Community/ModPerl.pm lib/Perl/Critic/Policy/Community/MultidimensionalArrayEmulation.pm lib/Perl/Critic/Policy/Community/OpenArgs.pm lib/Perl/Critic/Policy/Community/OverloadOptions.pm lib/Perl/Critic/Policy/Community/POSIXImports.pm lib/Perl/Critic/Policy/Community/PackageMatchesFilename.pm lib/Perl/Critic/Policy/Community/PreferredAlternatives.pm lib/Perl/Critic/Policy/Community/Prototypes.pm lib/Perl/Critic/Policy/Community/SplitQuotedPattern.pm lib/Perl/Critic/Policy/Community/StrictWarnings.pm lib/Perl/Critic/Policy/Community/Threads.pm lib/Perl/Critic/Policy/Community/Wantarray.pm lib/Perl/Critic/Policy/Community/WarningsSwitch.pm lib/Perl/Critic/Policy/Community/WhileDiamondDefaultAssignment.pm perlcritic.rc prereqs.yml t/00-report-prereqs.dd t/00-report-prereqs.t t/Community/AmpersandSubCalls.run t/Community/ArrayAssignAref.run t/Community/BarewordFilehandles.run t/Community/ConditionalDeclarations.run t/Community/ConditionalImplicitReturn.run t/Community/DeprecatedFeatures.run t/Community/DiscouragedModules.run t/Community/DollarAB.run t/Community/Each.run t/Community/EmptyReturn.run t/Community/IndirectObjectNotation.run t/Community/LexicalForeachIterator.run t/Community/LoopOnHash.run t/Community/ModPerl.run t/Community/MultidimensionalArrayEmulation.run t/Community/OpenArgs.run t/Community/OverloadOptions.run t/Community/POSIXImports.run t/Community/PackageMatchesFilename.run t/Community/PreferredAlternatives.run t/Community/Prototypes.run t/Community/SplitQuotedPattern.run t/Community/StrictWarnings.run t/Community/Threads.run t/Community/Wantarray.run t/Community/WarningsSwitch.run t/Community/WhileDiamondDefaultAssignment.run t/policies.t xt/author/critic.t xt/author/pod-syntax.t Build.PL100644001750001750 775214734076151 17402 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4# This Build.PL for Perl-Critic-Community was generated by # Dist::Zilla::Plugin::ModuleBuildTiny::Fallback 0.027 use strict; use warnings; my %configure_requires = ( 'Module::Build::Tiny' => '0.034', ); my %errors = map { eval "require $_; $_->VERSION($configure_requires{$_}); 1"; $_ => $@, } keys %configure_requires; if (!grep $_, values %errors) { # This section for Perl-Critic-Community was generated by Dist::Zilla::Plugin::ModuleBuildTiny 0.017. use strict; use warnings; use 5.010001; # use Module::Build::Tiny 0.034; Module::Build::Tiny::Build_PL(); } else { if (not $ENV{PERL_MB_FALLBACK_SILENCE_WARNING}) { warn <<'EOW' *** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING *** If you're seeing this warning, your toolchain is really, really old* and you'll almost certainly have problems installing CPAN modules from this century. But never fear, dear user, for we have the technology to fix this! If you're using CPAN.pm to install things, then you can upgrade it using: cpan CPAN If you're using CPANPLUS to install things, then you can upgrade it using: cpanp CPANPLUS If you're using cpanminus, you shouldn't be seeing this message in the first place, so please file an issue on github. This public service announcement was brought to you by the Perl Toolchain Gang, the irc.perl.org #toolchain IRC channel, and the number 42. ---- * Alternatively, you are running this file manually, in which case you need to learn to first fulfill all configure requires prerequisites listed in META.yml or META.json -- or use a cpan client to install this distribution. You can also silence this warning for future installations by setting the PERL_MB_FALLBACK_SILENCE_WARNING environment variable, but please don't do that until you fix your toolchain as described above. Errors from configure prereqs: EOW . do { require Data::Dumper; Data::Dumper->new([ \%errors ])->Indent(2)->Terse(1)->Sortkeys(1)->Dump; }; sleep 10 if -t STDIN && (-t STDOUT || !(-f STDOUT || -c STDOUT)); } # This section was automatically generated by Dist::Zilla::Plugin::ModuleBuild v6.032. use strict; use warnings; require Module::Build; Module::Build->VERSION(0.28); my %module_build_args = ( "configure_requires" => { "Module::Build::Tiny" => "0.034" }, "dist_abstract" => "Community-inspired Perl::Critic policies", "dist_author" => [ "Dan Book " ], "dist_name" => "Perl-Critic-Community", "dist_version" => "v1.0.4", "license" => "artistic_2", "module_name" => "Perl::Critic::Community", "recursive_test_files" => 1, "requires" => { "Carp" => 0, "Exporter" => 0, "List::Util" => "1.33", "PPI" => "1.254", "Path::Tiny" => "0.101", "Perl::Critic" => "1.126", "Perl::Critic::Policy::Objects::ProhibitIndirectSyntax" => "1.126", "Perl::Critic::Policy::Plicease::ProhibitArrayAssignAref" => "100.00", "Perl::Critic::Policy::Subroutines::ProhibitAmpersandSigils" => "1.126", "Perl::Critic::Policy::Variables::ProhibitConditionalDeclarations" => "1.126", "Perl::Critic::Policy::Variables::ProhibitLoopOnHash" => "0.005", "Perl::Critic::Policy::Variables::RequireLexicalLoopIterators" => "1.126", "Scalar::Util" => 0, "parent" => 0, "perl" => "5.010001", "version" => 0 }, "test_requires" => { "File::Spec" => 0, "Module::Metadata" => 0, "Test::More" => 0 } ); my %fallback_build_requires = ( "File::Spec" => 0, "Module::Metadata" => 0, "Test::More" => 0 ); unless ( eval { Module::Build->VERSION(0.4004) } ) { delete $module_build_args{test_requires}; $module_build_args{build_requires} = \%fallback_build_requires; } my $build = Module::Build->new(%module_build_args); $build->create_build_script; } META.json100644001750001750 2007714734076151 17542 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4{ "abstract" : "Community-inspired Perl::Critic policies", "author" : [ "Dan Book " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.032, CPAN::Meta::Converter version 2.150010", "license" : [ "artistic_2" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Perl-Critic-Community", "no_index" : { "directory" : [ "eg", "examples", "inc", "share", "t", "xt" ] }, "prereqs" : { "configure" : { "requires" : { "Module::Build::Tiny" : "0.034" } }, "develop" : { "requires" : { "Test::Perl::Critic" : "0", "Test::Pod" : "1.41" }, "suggests" : { "App::PPI::Dumper" : "0" } }, "runtime" : { "requires" : { "Carp" : "0", "Exporter" : "0", "List::Util" : "1.33", "PPI" : "1.254", "Path::Tiny" : "0.101", "Perl::Critic" : "1.126", "Perl::Critic::Policy::Objects::ProhibitIndirectSyntax" : "1.126", "Perl::Critic::Policy::Plicease::ProhibitArrayAssignAref" : "100.00", "Perl::Critic::Policy::Subroutines::ProhibitAmpersandSigils" : "1.126", "Perl::Critic::Policy::Variables::ProhibitConditionalDeclarations" : "1.126", "Perl::Critic::Policy::Variables::ProhibitLoopOnHash" : "0.005", "Perl::Critic::Policy::Variables::RequireLexicalLoopIterators" : "1.126", "Scalar::Util" : "0", "parent" : "0", "perl" : "5.010001", "version" : "0" } }, "test" : { "recommends" : { "CPAN::Meta" : "2.120900" }, "requires" : { "File::Spec" : "0", "Module::Metadata" : "0", "Test::More" : "0" } } }, "provides" : { "Perl::Critic::Community" : { "file" : "lib/Perl/Critic/Community.pm", "version" : "v1.0.4" }, "Perl::Critic::Community::Utils" : { "file" : "lib/Perl/Critic/Community/Utils.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::AmpersandSubCalls" : { "file" : "lib/Perl/Critic/Policy/Community/AmpersandSubCalls.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::ArrayAssignAref" : { "file" : "lib/Perl/Critic/Policy/Community/ArrayAssignAref.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::BarewordFilehandles" : { "file" : "lib/Perl/Critic/Policy/Community/BarewordFilehandles.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::ConditionalDeclarations" : { "file" : "lib/Perl/Critic/Policy/Community/ConditionalDeclarations.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::ConditionalImplicitReturn" : { "file" : "lib/Perl/Critic/Policy/Community/ConditionalImplicitReturn.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::DeprecatedFeatures" : { "file" : "lib/Perl/Critic/Policy/Community/DeprecatedFeatures.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::DiscouragedModules" : { "file" : "lib/Perl/Critic/Policy/Community/DiscouragedModules.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::DollarAB" : { "file" : "lib/Perl/Critic/Policy/Community/DollarAB.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::Each" : { "file" : "lib/Perl/Critic/Policy/Community/Each.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::EmptyReturn" : { "file" : "lib/Perl/Critic/Policy/Community/EmptyReturn.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::IndirectObjectNotation" : { "file" : "lib/Perl/Critic/Policy/Community/IndirectObjectNotation.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::LexicalForeachIterator" : { "file" : "lib/Perl/Critic/Policy/Community/LexicalForeachIterator.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::LoopOnHash" : { "file" : "lib/Perl/Critic/Policy/Community/LoopOnHash.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::ModPerl" : { "file" : "lib/Perl/Critic/Policy/Community/ModPerl.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::MultidimensionalArrayEmulation" : { "file" : "lib/Perl/Critic/Policy/Community/MultidimensionalArrayEmulation.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::OpenArgs" : { "file" : "lib/Perl/Critic/Policy/Community/OpenArgs.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::OverloadOptions" : { "file" : "lib/Perl/Critic/Policy/Community/OverloadOptions.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::POSIXImports" : { "file" : "lib/Perl/Critic/Policy/Community/POSIXImports.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::PackageMatchesFilename" : { "file" : "lib/Perl/Critic/Policy/Community/PackageMatchesFilename.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::PreferredAlternatives" : { "file" : "lib/Perl/Critic/Policy/Community/PreferredAlternatives.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::Prototypes" : { "file" : "lib/Perl/Critic/Policy/Community/Prototypes.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::SplitQuotedPattern" : { "file" : "lib/Perl/Critic/Policy/Community/SplitQuotedPattern.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::StrictWarnings" : { "file" : "lib/Perl/Critic/Policy/Community/StrictWarnings.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::Threads" : { "file" : "lib/Perl/Critic/Policy/Community/Threads.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::Wantarray" : { "file" : "lib/Perl/Critic/Policy/Community/Wantarray.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::WarningsSwitch" : { "file" : "lib/Perl/Critic/Policy/Community/WarningsSwitch.pm", "version" : "v1.0.4" }, "Perl::Critic::Policy::Community::WhileDiamondDefaultAssignment" : { "file" : "lib/Perl/Critic/Policy/Community/WhileDiamondDefaultAssignment.pm", "version" : "v1.0.4" } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/Grinnz/Perl-Critic-Community/issues" }, "homepage" : "https://github.com/Grinnz/Perl-Critic-Community", "repository" : { "type" : "git", "url" : "https://github.com/Grinnz/Perl-Critic-Community.git", "web" : "https://github.com/Grinnz/Perl-Critic-Community" }, "x_IRC" : "irc://irc.libera.chat/#perl" }, "version" : "v1.0.4", "x_contributors" : [ "Amory Meltzer ", "Dan Book ", "Dan Book ", "David Cantrell ", "Graham Knop ", "Graham Ollis ", "Ian Bradley ", "Karen Etheridge ", "Nicolas Rochelemagne ", "Ryan Voots ", "Tomasz Konojacki ", "William Taylor " ], "x_generated_by_perl" : "v5.40.0", "x_serialization_backend" : "Cpanel::JSON::XS version 4.38", "x_spdx_expression" : "Artistic-2.0" } prereqs.yml100644001750001750 125014734076151 20275 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4runtime: requires: perl: '5.010001' Carp: 0 Exporter: 0 List::Util: '1.33' parent: 0 Path::Tiny: '0.101' Perl::Critic: '1.126' Perl::Critic::Policy::Objects::ProhibitIndirectSyntax: '1.126' Perl::Critic::Policy::Subroutines::ProhibitAmpersandSigils: '1.126' Perl::Critic::Policy::Plicease::ProhibitArrayAssignAref: '100.00' Perl::Critic::Policy::Variables::ProhibitConditionalDeclarations: '1.126' Perl::Critic::Policy::Variables::ProhibitLoopOnHash: '0.005' Perl::Critic::Policy::Variables::RequireLexicalLoopIterators: '1.126' PPI: '1.254' Scalar::Util: 0 version: 0 develop: suggests: App::PPI::Dumper: 0 t000755001750001750 014734076151 16176 5ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4policies.t100644001750001750 13614734076151 20312 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/tuse strict; use warnings; use Test::Perl::Critic::Policy 'all_policies_ok'; all_policies_ok; perlcritic.rc100644001750001750 3714734076151 20521 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4theme = community severity = 1 CONTRIBUTING.md100644001750001750 1055514734076151 20352 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4# HOW TO CONTRIBUTE Thank you for considering contributing to this distribution. This file contains instructions that will help you work with the source code. The distribution is managed with [Dist::Zilla](https://metacpan.org/pod/Dist::Zilla). This means that many of the usual files you might expect are not in the repository, but are generated at release time. Some generated files are kept in the repository as a convenience (e.g. Build.PL/Makefile.PL and META.json). Generally, **you do not need Dist::Zilla to contribute patches**. You may need Dist::Zilla to create a tarball. See below for guidance. ## Getting dependencies If you have App::cpanminus 1.6 or later installed, you can use [cpanm](https://metacpan.org/pod/cpanm) to satisfy dependencies like this: $ cpanm --installdeps --with-develop . You can also run this command (or any other cpanm command) without installing App::cpanminus first, using the fatpacked `cpanm` script via curl or wget: $ curl -L https://cpanmin.us | perl - --installdeps --with-develop . $ wget -qO - https://cpanmin.us | perl - --installdeps --with-develop . Otherwise, look for either a `cpanfile`, `prereqs.json`/`prereqs.yml`, or `META.json` file for a list of dependencies to satisfy. ## Running tests You can run tests directly using the `prove` tool: $ prove -l $ prove -lv t/some_test_file.t For most of my distributions, `prove` is entirely sufficient for you to test any patches you have. I use `prove` for 99% of my testing during development. ## Code style and tidying Please try to match any existing coding style. If there is a `.perltidyrc` file, please install Perl::Tidy and use perltidy before submitting patches. ## Installing and using Dist::Zilla [Dist::Zilla](https://metacpan.org/pod/Dist::Zilla) is a very powerful authoring tool, optimized for maintaining a large number of distributions with a high degree of automation, but it has a large dependency chain, a bit of a learning curve and requires a number of author-specific plugins. To install it from CPAN, I recommend one of the following approaches for the quickest installation: # using CPAN.pm, but bypassing non-functional pod tests $ cpan TAP::Harness::Restricted $ PERL_MM_USE_DEFAULT=1 HARNESS_CLASS=TAP::Harness::Restricted cpan Dist::Zilla # using cpanm, bypassing *all* tests $ cpanm -n Dist::Zilla In either case, it's probably going to take about 10 minutes. Go for a walk, go get a cup of your favorite beverage, take a bathroom break, or whatever. When you get back, Dist::Zilla should be ready for you. Then you need to install any plugins specific to this distribution: $ dzil authordeps --missing | cpanm You can use Dist::Zilla to install the distribution's dependencies if you haven't already installed them with cpanm: $ dzil listdeps --missing --develop | cpanm You can instead combine these two steps into one command by installing Dist::Zilla::App::Command::installdeps then running: $ dzil installdeps Once everything is installed, here are some dzil commands you might try: $ dzil build $ dzil test $ dzil regenerate You can learn more about Dist::Zilla at http://dzil.org/ ## Other notes This distribution maintains the generated `META.json` and either `Makefile.PL` or `Build.PL` in the repository. This allows two things: [Travis CI](https://travis-ci.org/) can build and test the distribution without requiring Dist::Zilla, and the distribution can be installed directly from Github or a local git repository using `cpanm` for testing (again, not requiring Dist::Zilla). $ cpanm git://github.com/Author/Distribution-Name.git $ cd Distribution-Name; cpanm . Contributions are preferred in the form of a Github pull request. See [Using pull requests](https://help.github.com/articles/using-pull-requests/) for further information. You can use the Github issue tracker to report issues without an accompanying patch. # CREDITS This file was adapted from an initial `CONTRIBUTING.mkdn` file from David Golden under the terms of the [CC0](https://creativecommons.org/share-your-work/public-domain/cc0/), with inspiration from the contributing documents from [Dist::Zilla::Plugin::Author::KENTNL::CONTRIBUTING](https://metacpan.org/pod/Dist::Zilla::Plugin::Author::KENTNL::CONTRIBUTING) and [Dist::Zilla::PluginBundle::Author::ETHER](https://metacpan.org/pod/Dist::Zilla::PluginBundle::Author::ETHER). author000755001750001750 014734076151 17670 5ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/xtcritic.t100644001750001750 20114734076151 21443 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/xt/author#!perl use strict; use warnings; use Test::Perl::Critic (-profile => "perlcritic.rc") x!! -e "perlcritic.rc"; all_critic_ok(); Community000755001750001750 014734076151 20162 5ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/tEach.run100644001750001750 35214734076151 21670 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name UseEach ## failures 2 ## cut while (($key, $value) = each %hash) { ... } while (($i, $elem) = each @array) { ... } ## name NoEach ## failures 0 ## cut foreach my $key (keys %hash) { ... } foreach my $i (0..$#array) { ... } 00-report-prereqs.t100644001750001750 1363214734076151 21757 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t#!perl use strict; use warnings; # This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.029 use Test::More tests => 1; use Module::Metadata; use File::Spec; # from $version::LAX my $lax_version_re = qr/(?: undef | (?: (?:[0-9]+) (?: \. | (?:\.[0-9]+) (?:_[0-9]+)? )? | (?:\.[0-9]+) (?:_[0-9]+)? ) | (?: v (?:[0-9]+) (?: (?:\.[0-9]+)+ (?:_[0-9]+)? )? | (?:[0-9]+)? (?:\.[0-9]+){2,} (?:_[0-9]+)? ) )/x; # hide optional CPAN::Meta modules from prereq scanner # and check if they are available my $cpan_meta = "CPAN::Meta"; my $cpan_meta_pre = "CPAN::Meta::Prereqs"; my $HAS_CPAN_META = eval "require $cpan_meta; $cpan_meta->VERSION('2.120900')" && eval "require $cpan_meta_pre"; ## no critic # Verify requirements? my $DO_VERIFY_PREREQS = 1; sub _max { my $max = shift; $max = ( $_ > $max ) ? $_ : $max for @_; return $max; } sub _merge_prereqs { my ($collector, $prereqs) = @_; # CPAN::Meta::Prereqs object if (ref $collector eq $cpan_meta_pre) { return $collector->with_merged_prereqs( CPAN::Meta::Prereqs->new( $prereqs ) ); } # Raw hashrefs for my $phase ( keys %$prereqs ) { for my $type ( keys %{ $prereqs->{$phase} } ) { for my $module ( keys %{ $prereqs->{$phase}{$type} } ) { $collector->{$phase}{$type}{$module} = $prereqs->{$phase}{$type}{$module}; } } } return $collector; } my @include = qw( PPI ); my @exclude = qw( ); # Add static prereqs to the included modules list my $static_prereqs = do './t/00-report-prereqs.dd'; # Merge all prereqs (either with ::Prereqs or a hashref) my $full_prereqs = _merge_prereqs( ( $HAS_CPAN_META ? $cpan_meta_pre->new : {} ), $static_prereqs ); # Add dynamic prereqs to the included modules list (if we can) my ($source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; my $cpan_meta_error; if ( $source && $HAS_CPAN_META && (my $meta = eval { CPAN::Meta->load_file($source) } ) ) { $full_prereqs = _merge_prereqs($full_prereqs, $meta->prereqs); } else { $cpan_meta_error = $@; # capture error from CPAN::Meta->load_file($source) $source = 'static metadata'; } my @full_reports; my @dep_errors; my $req_hash = $HAS_CPAN_META ? $full_prereqs->as_string_hash : $full_prereqs; # Add static includes into a fake section for my $mod (@include) { $req_hash->{other}{modules}{$mod} = 0; } for my $phase ( qw(configure build test runtime develop other) ) { next unless $req_hash->{$phase}; next if ($phase eq 'develop' and not $ENV{AUTHOR_TESTING}); for my $type ( qw(requires recommends suggests conflicts modules) ) { next unless $req_hash->{$phase}{$type}; my $title = ucfirst($phase).' '.ucfirst($type); my @reports = [qw/Module Want Have/]; for my $mod ( sort keys %{ $req_hash->{$phase}{$type} } ) { next if grep { $_ eq $mod } @exclude; my $want = $req_hash->{$phase}{$type}{$mod}; $want = "undef" unless defined $want; $want = "any" if !$want && $want == 0; if ($mod eq 'perl') { push @reports, ['perl', $want, $]]; next; } my $req_string = $want eq 'any' ? 'any version required' : "version '$want' required"; my $file = $mod; $file =~ s{::}{/}g; $file .= ".pm"; my ($prefix) = grep { -e File::Spec->catfile($_, $file) } @INC; if ($prefix) { my $have = Module::Metadata->new_from_file( File::Spec->catfile($prefix, $file) )->version; $have = "undef" unless defined $have; push @reports, [$mod, $want, $have]; if ( $DO_VERIFY_PREREQS && $HAS_CPAN_META && $type eq 'requires' ) { if ( $have !~ /\A$lax_version_re\z/ ) { push @dep_errors, "$mod version '$have' cannot be parsed ($req_string)"; } elsif ( ! $full_prereqs->requirements_for( $phase, $type )->accepts_module( $mod => $have ) ) { push @dep_errors, "$mod version '$have' is not in required range '$want'"; } } } else { push @reports, [$mod, $want, "missing"]; if ( $DO_VERIFY_PREREQS && $type eq 'requires' ) { push @dep_errors, "$mod is not installed ($req_string)"; } } } if ( @reports ) { push @full_reports, "=== $title ===\n\n"; my $ml = _max( map { length $_->[0] } @reports ); my $wl = _max( map { length $_->[1] } @reports ); my $hl = _max( map { length $_->[2] } @reports ); if ($type eq 'modules') { splice @reports, 1, 0, ["-" x $ml, "", "-" x $hl]; push @full_reports, map { sprintf(" %*s %*s\n", -$ml, $_->[0], $hl, $_->[2]) } @reports; } else { splice @reports, 1, 0, ["-" x $ml, "-" x $wl, "-" x $hl]; push @full_reports, map { sprintf(" %*s %*s %*s\n", -$ml, $_->[0], $wl, $_->[1], $hl, $_->[2]) } @reports; } push @full_reports, "\n"; } } } if ( @full_reports ) { diag "\nVersions for all modules listed in $source (including optional ones):\n\n", @full_reports; } if ( $cpan_meta_error || @dep_errors ) { diag "\n*** WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ***\n"; } if ( $cpan_meta_error ) { my ($orig_source) = grep { -f } 'MYMETA.json', 'MYMETA.yml'; diag "\nCPAN::Meta->load_file('$orig_source') failed with: $cpan_meta_error\n"; } if ( @dep_errors ) { diag join("\n", "\nThe following REQUIRED prerequisites were not satisfied:\n", @dep_errors, "\n" ); } pass('Reported prereqs'); # vim: ts=4 sts=4 sw=4 et: pod-syntax.t100644001750001750 25214734076151 22302 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/xt/author#!perl # This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests. use strict; use warnings; use Test::More; use Test::Pod 1.41; all_pod_files_ok(); 00-report-prereqs.dd100644001750001750 455214734076151 22064 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/tdo { my $x = { 'configure' => { 'requires' => { 'Module::Build::Tiny' => '0.034' } }, 'develop' => { 'requires' => { 'Test::Perl::Critic' => '0', 'Test::Pod' => '1.41' }, 'suggests' => { 'App::PPI::Dumper' => '0' } }, 'runtime' => { 'requires' => { 'Carp' => '0', 'Exporter' => '0', 'List::Util' => '1.33', 'PPI' => '1.254', 'Path::Tiny' => '0.101', 'Perl::Critic' => '1.126', 'Perl::Critic::Policy::Objects::ProhibitIndirectSyntax' => '1.126', 'Perl::Critic::Policy::Plicease::ProhibitArrayAssignAref' => '100.00', 'Perl::Critic::Policy::Subroutines::ProhibitAmpersandSigils' => '1.126', 'Perl::Critic::Policy::Variables::ProhibitConditionalDeclarations' => '1.126', 'Perl::Critic::Policy::Variables::ProhibitLoopOnHash' => '0.005', 'Perl::Critic::Policy::Variables::RequireLexicalLoopIterators' => '1.126', 'Scalar::Util' => '0', 'parent' => '0', 'perl' => '5.010001', 'version' => '0' } }, 'test' => { 'recommends' => { 'CPAN::Meta' => '2.120900' }, 'requires' => { 'File::Spec' => '0', 'Module::Metadata' => '0', 'Test::More' => '0' } } }; $x; }ModPerl.run100644001750001750 44414734076151 22374 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name UseModPerl1 ## failures 4 ## cut use Apache; use Apache::Constants; use Apache::Registry; use Apache::Request; ## name UseModPerl2 ## failures 4 ## cut use Apache2::Const; use ModPerl::Const; use ModPerl::Registry; use Apache2::Request; ## name NoModPerl ## failures 0 ## cut 1; Threads.run100644001750001750 14214734076151 22417 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name UseThreads ## failures 1 ## cut use threads; ## name NoThreads ## failures 0 ## cut 1; DollarAB.run100644001750001750 161114734076151 22467 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name OutsideSort ## failures 4 ## cut $a = 1; $b = 2; asdf { $a = 1; $b = 2; }; ## name InsideSort ## failures 0 ## cut sort { $a = 1; $b = 2; } (); ## name MethodSort ## failures 0 ## cut $collection->sort(sub { $a = 1; $b = 2 }); ## name HashKey ## failures 0 ## cut push @c, [ @row{sort { $a <=> $b } keys %row } ]; ## name ApparentSigil ## failures 0 ## cut my $x = $b[1]||" "; ## name DereferenceBlock ## failures 0 ## cut sort { @{$a} <=> @{$b} } (); sort { scalar(@{$a->{ids}}) <=> scalar(@{$b->{ids}}) } (); ## name InnerBlock ## failures 0 ## cut sort { {; $a } } (); ## name AllowedFunctions ## failures 0 ## cut sort { $a; $b } (); reduce { $a; $b } (); pairgrep { $a; $b } (); pairfirst { $a; $b } (); pairmap { $a; $b } (); pairwise { $a; $b } (); ## name CustomFunctions ## failures 0 ## parms { extra_pair_functions => 'foo bar' } ## cut foo { $a; $b }; bar { $a; $b }; OpenArgs.run100644001750001750 67314734076151 22554 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name OpenOneArg ## failures 2 ## cut open FILE or die; open my $fh; ## name OpenTwoArgs ## failures 2 ## cut open FILE, "<$filename" or die; open my $fh, "<$filename"; ## name OpenThreeArgs ## failures 0 ## cut open FILE, '<', $filename or die; open my $fh, '<', $filename; ## name OpenFourArgs ## failures 0 ## cut open my $fh, '-|', 'ls', '-al'; ## name OpenFork ## failures 0 ## cut open my $child, '-|'; open my $child, '|-'; Wantarray.run100600001750001750 46614734076151 22776 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name UseWantarray ## failures 1 ## cut return wantarray ? () : undef; ## name UseCoreWantArray ## failures 1 ## cut return CORE::wantarray ? () : undef; ## name UseCoreApostrapheWantArray ## failures 1 ## cut return CORE'wantarray ? () : undef; ## name NoWantarray ## failures 0 ## cut return undef; LoopOnHash.run100644001750001750 143014734076151 23060 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name ForeachHash ## failures 4 ## cut foreach my $foo (%hash) { ... } for my $foo (%hash) { ... } foo foreach %hash; foo for %hash; ## name ForeachKeys ## failures 0 ## cut foreach my $foo (keys %hash) { ... } for my $foo (keys %hash) { ... } foo foreach keys %hash; foo for keys %hash; ## name ForeachValues ## failures 0 ## cut foreach my $foo (values %hash) { ... } for my $foo (values %hash) { ... } foo foreach values %hash; foo for values %hash; ## name ForeachCopyRef ## failures 0 ## cut foreach my $foo (@{[%hash]}) { ... } for my $foo (@{[%hash]}) { ... } foo foreach @{[%hash]}; foo for @{[%hash]}; ## name ForeachCopyVar ## failures 0 ## cut foreach my $foo (my @d = %hash) { ... } for my $foo (my @d = %hash) { ... } foo foreach my @d = %hash; foo for my @d = %hash; Prototypes.run100644001750001750 156214734076151 23244 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name WithPrototype ## failures 1 ## cut sub foo ($) { ... } ## name WithSignature ## failures 0 ## cut use feature 'signatures'; sub foo ($foo) { ... } ## name BundleSignature ## failures 0 ## cut use v5.36; sub foo ($foo) { ... } ## name ExperimentalSignature ## failures 0 ## cut use experimental 'signatures'; sub foo ($foo) { ... } ## name MojoSignature ## failures 0 ## cut use Mojo::Base -base, -signatures; sub foo ($foo) { ... } ## name MojoLiteSignature ## failures 0 ## cut use Mojolicious::Lite -signatures; sub foo ($foo) { ... } ## name CustomSignature ## failures 0 ## parms { signature_enablers => 'MyApp::Base' } ## cut use MyApp::Base; sub foo ($foo) { ... } ## name NoPrototype ## failures 0 ## cut sub foo { ... } ## name EmptyPrototype ## failures 0 ## cut sub foo () { ... } ## name SubPrototype ## failures 0 ## cut sub foo (&;@) { ... } EmptyReturn.run100644001750001750 172514734076151 23353 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name EmptyReturn ## failures 1 ## cut sub foo { return; return $foo; } ## name BareReturn ## failures 1 ## cut sub foo { return $foo; return } ## name ReturnEmptyList ## failures 0 ## cut sub foo { return (); return ($foo, $bar); } ## name ReturnScalar ## failures 0 ## cut sub foo { return undef; return $foo; } ## name ReturnList ## failures 0 ## cut sub foo { return 1, 2, 3; return $foo; } ## name ReturnModified ## failures 1 ## cut sub foo { return if bar(); return $foo; } ## name ReturnMidStatement ## failures 1 ## cut sub foo { bar() or return; return $foo; } ## name OnlyEmptyReturn ## failures 0 ## cut sub foo { return if bar(); return; } ## name ReturnInStructure ## failures 1 ## cut sub foo { return if bar(); if (1) { return $foo } } ## name OnlyEmptyReturnInStructure ## failures 0 ## cut sub foo { return if bar(); if (1) { return } } ## name ReturnInCode ## failures 0 ## cut sub foo { return if bar(); my $code = sub { return $foo }; } Critic000755001750001750 014734076151 20620 5ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/PerlCommunity.pm100644001750001750 1102314734076151 23317 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Criticpackage Perl::Critic::Community; use strict; use warnings; our $VERSION = 'v1.0.4'; 1; =head1 NAME Perl::Critic::Community - Community-inspired Perl::Critic policies =head1 SYNOPSIS $ perlcritic --theme community script.pl $ perlcritic --theme community lib/ # .perlcriticrc theme = community severity = 1 =head1 DESCRIPTION A set of L policies to enforce the practices generally recommended by subsets of the Perl community, particularly on L. Formerly known as L. Because this policy "theme" is designed to be used with zero configuration on the command line, some duplication will occur if it is used in combination with core L policies. =head1 AFFILIATION This module has no functionality, but instead contains documentation for this distribution and acts as a means of pulling other modules into a bundle. All of the Policy modules contained herein will have an "AFFILIATION" section announcing their participation in this grouping. =head1 POLICIES =over =item L Don't use C<&> to call subroutines =item L Don't assign an anonymous arrayref to an array =item L Don't use bareword filehandles other than built-ins =item L Don't declare variables conditionally =item L Don't end a subroutine with a conditional block =item L Avoid features that have been deprecated or removed from Perl =item L Various modules discouraged from use =item L Don't use C<$a> or C<$b> as variable names outside C =item L Don't use C to iterate through a hash =item L Don't use C with no arguments =item L Don't call methods indirectly =item L Don't use undeclared foreach loop iterators =item L Don't loop over hashes =item L Don't use C to write web applications =item L Don't use multidimensional array emulation =item L Always use the three-argument form of C =item L Don't use L without specifying a bool overload and enabling fallback =item L Module files should declare a package matching the filename =item L Don't use L without specifying an import list =item L Various modules with preferred alternatives =item L Don't use function prototypes =item L Quote the split() pattern argument with regex slashes =item L Always use L and L, or a module that imports these =item L Interpreter-based threads are officially discouraged =item L Don't write context-sensitive functions using C =item L Scripts should not use the C<-w> switch on the shebang line =item L Don't use C with implicit assignment to C<$_> =back =head1 CONFIGURATION AND ENVIRONMENT All policies included are in the "community" theme. See the L documentation for how to make use of this. =head1 AUTHOR Dan Book, C =head1 CONTRIBUTORS =over =item Graham Knop (haarg) =item H.Merijn Brand (Tux) =item John SJ Anderson (genehack) =item Matt S Trout (mst) =item William Taylor (willt) =back =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L POSIXImports.run100644001750001750 43714734076151 23314 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name DefaultImport ## failures 1 ## cut use POSIX; ## name DefaultImportWithVersion ## failures 1 ## cut use POSIX 1; ## name EmptyImport ## failures 0 ## cut use POSIX (); ## name ExplicitImport ## failures 0 ## cut use POSIX 'strftime'; use POSIX qw(strftime strcpy strchr); StrictWarnings.run100644001750001750 235014734076151 24031 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name HasStrictWarnings ## failures 0 ## cut use strict; use warnings; ## name NoStrict ## failures 1 ## cut use warnings; ## name NoWarnings ## failures 1 ## cut use strict; ## name NoStrictWarnings ## failures 1 ## cut 1; ## name Importer ## failures 0 ## cut use Moose; ## name IncompleteImporter ## failures 1 ## cut use common::sense; ## name VersionStrict1 ## failures 0 ## cut use 5.012; use warnings; ## name VersionStrict2 ## failures 0 ## cut use v5.12.0; use warnings; ## name VersionStrict3 ## failures 0 ## cut use 5.12.0; use warnings; ## name VersionStrict4 ## failures 1 ## cut use 5.010001; use warnings; ## name VersionStrict5 ## failures 1 ## cut use v5.10.1; use warnings; ## name VersionStrict6 ## failures 1 ## cut use 5.10.1; use warnings; ## name VersionWarnings1 ## failures 0 ## cut use 5.036; ## name VersionWarnings2 ## failures 0 ## cut use v5.36; ## name VersionWarnings3 ## failures 0 ## cut use 5.36.0; ## name VersionWarnings4 ## failures 1 ## cut use 5.034001; ## name VersionWarnings5 ## failures 1 ## cut use v5.34; ## name VersionWarnings6 ## failures 1 ## cut use 5.34.1; ## name CustomImporter ## failures 0 ## parms { extra_importers => 'MyApp::Base' } ## cut use MyApp::Base; WarningsSwitch.run100644001750001750 76114734076151 24006 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name HasSwitch ## failures 1 ## cut #!/usr/bin/perl -w ## name UppercaseSwitch ## failures 1 ## cut #!/usr/bin/perl -W ## name EmbeddedSwitch ## failures 1 ## cut #!/usr/bin/perl -w -T ## name BundledSwitch1 ## failures 1 ## cut #!/usr/bin/perl -wT ## name BundledSwitch2 ## failures 1 ## cut #!/usr/bin/perl -Tw ## name BundledSwitch3 ## failures 1 ## cut #!/usr/bin/perl -TwT ## name NoSwitch ## failures 0 ## cut #!/usr/bin/perl -T ## name NoShebang ## failures 0 ## cut package Foo; ArrayAssignAref.run100644001750001750 55314734076151 24054 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name AssignAref ## failures 2 ## cut @arr = []; @arr = [1,2,3]; ## name AssignList ## failures 0 ## cut @arr = (); @arr = (1,2,3); ## name AssignArefInList ## failures 0 ## cut @arr = ([]); @arr = ([1,2,3]); ## name AssignListOfAref ## failures 0 ## cut @arr = ([],[],[]); ## name AssignNonAref ## failures 0 ## cut @arr = 1; @arr = {}; @arr = 1..10; OverloadOptions.run100644001750001750 156514734076151 24206 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name EmptyOverload ## failures 0 ## cut use overload; use overload (); use overload qw(); ## name NoBoolOverload ## failures 2 ## cut use overload '""' => sub { $_[0]->name }, fallback => 1; use overload ('""', sub { $_[0]->name }), qw(fallback 1); ## name NoFallback ## failures 2 ## cut use overload '""' => sub { $_[0]->name }, bool => sub {1}; use overload (q{""}, sub { $_[0]->name }, "bool", sub {1}); ## name UndefFallback ## failures 2 ## cut use overload bool => sub {1}, fallback => undef; use overload bool => sub {1}, 'fallback'; ## name NoBoolOrFallback ## failures 2 ## cut use overload '""' => sub { $_[0]->name }; use overload ('""', sub { $_[0]->name }); ## name BoolAndFallback ## failures 0 ## cut use overload '""' => sub { $_[0]->name }, bool => sub {1}, fallback => 1; use overload (qq{""}, sub { $_[0]->name }, (q{bool}, sub {1})), qw(fallback 1); AmpersandSubCalls.run100644001750001750 42614734076151 24375 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name AmpersandWithArgs ## failures 2 ## cut &foo(1,2,3); &foo 1,2,3; ## name AmpersandNoArgs ## failures 2 ## cut &foo(); &foo; ## name SubRef ## failures 0 ## cut my $ref = \&foo; ## name AmpersandExemptions ## failures 0 ## cut goto &foo; defined &foo; exists &foo; Community000755001750001750 014734076151 22604 5ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/CriticUtils.pm100644001750001750 444714734076151 24413 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Communitypackage Perl::Critic::Community::Utils; use strict; use warnings; use Carp 'croak'; use Exporter 'import'; use Scalar::Util 'blessed'; our $VERSION = 'v1.0.4'; our @EXPORT_OK = qw(is_empty_return is_structural_block); my %modifiers = map { ($_ => 1) } qw(if unless while until for foreach when); my %compound = map { ($_ => 1) } qw(if unless while until for foreach given); sub is_empty_return { my $elem = shift; croak 'is_empty_return must be called with a PPI::Token::Word return element' unless blessed $elem and $elem->isa('PPI::Token::Word') and $elem eq 'return'; my $next = $elem->snext_sibling || return 1; return 1 if $next->isa('PPI::Token::Structure') and $next eq ';'; return 1 if $next->isa('PPI::Token::Word') and exists $modifiers{$next}; return 0; } sub is_structural_block { my $elem = shift; croak 'is_structural_block must be called with a PPI::Structure::Block element' unless blessed $elem and $elem->isa('PPI::Structure::Block'); if (my $parent = $elem->parent) { if ($parent->isa('PPI::Statement::Compound') and my $first = $parent->schild(0)) { return 1 if $first->isa('PPI::Token::Word') and exists $compound{$first}; } } # TODO: Allow bare blocks or blocks with labels return 0; } 1; =head1 NAME Perl::Critic::Community::Utils - Utility functions for the Community policy set =head1 DESCRIPTION This module contains utility functions for use in L policies. All functions are exportable on demand. =head1 FUNCTIONS =head2 is_empty_return my $bool = is_empty_return($elem); Tests whether a L C element represents an empty C statement. This function returns false for C. =head2 is_structural_block my $bool = is_structural_block($elem); Tests whether a L element is structural, and does not introduce a new calling context. This function currently only returns true for blocks in compound statements such as C and C, but may be extended to cover more cases in the future. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L, L DeprecatedFeatures.run100644001750001750 504314734076151 24611 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name GoodFeatures ## failures 0 ## cut my $x : Foo = 1; use UNIVERSAL (); UNIVERSAL->can('foo'); use POSIX (); for my $foo (qw(foo bar)) { ... } 1 for qw(foo bar); do { ... }; do '...'; do $foo; isalnum $foo; isalpha $foo; iscntrl $foo; isdigit $foo; isgraph $foo; islower $foo; isprint $foo; ispunct $foo; isspace $foo; isupper $foo; isxdigit $foo; tmpnam $foo; defined $foo; defined $foo[0]; defined $foo{bar}; defined &foo; $obj->defined(@foo); foo ? bar ? 'foo' : 'bar' : 'baz'; foo ? bar ? foo : bar : baz; $foo =~ m?foo?; $foo =~ s?foo?bar?; "\N{FOO BAR}"; `\N{FOO BAR}`; qx(\N{FOO BAR}); qq{\N{FOO BAR}}; qr/\N{FOO BAR}/; m'\N{FOO BAR}'; s{\N{FOO BAR}}{}; keys %hash; keys %$href; keys(%{$href}); keys %{$foo{bar}[5]}; keys $foo->{bar}[5]->%*; keys $foo->{bar}[5]->%* > 4; shift(@array); shift @$aref; shift @{$aref}; shift(@{$foo->{bar}[5]}); shift $foo->{bar}[5]->@*; shift; shift(); Foo->shift($foo); require Foo::Bar; use Foo::Bar; no Foo::Bar; require '::Foo::Bar.pm'; qr/\cT\\C/; m/\cT\\C/; chdir; chdir(); chdir 'foo'; chdir(getcwd); << 'foo'; foo <<''; <import; use UNIVERSAL; use UNIVERSAL 'foo'; for my $foo qw(foo bar) { ... } do foo(...); do &foo(...); do $foo(...); POSIX::isalnum($foo); POSIX::isalpha($foo); POSIX::iscntrl($foo); POSIX::isdigit($foo); POSIX::isgraph($foo); POSIX::islower($foo); POSIX::isprint($foo); POSIX::ispunct($foo); POSIX::isspace($foo); POSIX::isupper($foo); POSIX::isxdigit($foo); POSIX::tmpnam($foo); defined @foo; defined %foo; defined(@foo); defined(%foo); $foo =~ ?foo?; "\N{FOO BAR}"; `\N{FOO BAR}`; qq{\N{FOO BAR}}; qx(\N{FOO BAR}); qr^\N{FOO BAR}^; m<\N{FOO BAR}>; s/\N{FOO BAR}//; each $ref; keys($ref); pop $foo->{bar}; push $foo{bar}[0]; shift($foo->[5]); splice $foo, $bar, $baz; unshift $ref, @bar; values $ref; require ::Foo::Bar; use ::Foo::Bar; no ::Foo::Bar; qr/\C/; m/\C/; chdir ''; chdir(qq()); chdir undef(); <<; (<<); {<<} << . bar; ## name POSIXDeprecations ## failures 12 ## cut use POSIX; isalnum $foo; isalpha $foo; iscntrl $foo; isdigit $foo; isgraph $foo; islower $foo; isprint $foo; ispunct $foo; isspace $foo; isupper $foo; isxdigit $foo; tmpnam $foo; ## name POSIXDeprecationsImported ## failures 12 ## cut use POSIX qw(isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tmpnam); isalnum $foo; isalpha $foo; iscntrl $foo; isdigit $foo; isgraph $foo; islower $foo; isprint $foo; ispunct $foo; isspace $foo; isupper $foo; isxdigit $foo; tmpnam $foo; DiscouragedModules.run100644001750001750 244714734076151 24641 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name GoodModules ## failures 0 ## cut use lib::relative; use CGI::Tiny; use Cpanel::JSON::XS; use Dancer2; use DBIx::Class; use Dir::Self; use Exception::Class; use File::Slurp::Tiny; use Future; use Future::AsyncAwait; use GeoIP2::Database::Reader; use IO::Async::Loop; use IO::Socket::IP; use JSON::MaybeXS; use JSON::PP; use Mad::Mapper; use Mojo::DOM; use Mojo::IOLoop; use Mojo::File; use Mojo::JSON; use Mojo::Template; use Mojolicious; use Moo; use Moose; use Path::Tiny; use Plack; use POE; use Switch::Plain; use Syntax::Keyword::Match; use Syntax::Keyword::Try; use Template; use Text::Xslate; with 'Throwable'; use Try; use Try::Tiny; use Web::Simple; use XML::LibXML; use XML::TreeBuilder; use XML::Twig; ## name BadModules ## failures 16 ## cut use Any::Moose; use AnyEvent; use Class::DBI; use CGI; use Coro; use Error; use File::Slurp; use FindBin; use HTML::Template; use IO::Socket::INET6; use IP::World; use JSON::Any; use JSON::XS; use Net::IRC; use Switch; use XML::Simple; ## name Allowed BadModules ## parms { allowed_modules => 'AnyEvent FindBin JSON::XS' }; ## failures 0 ## cut use AnyEvent; use FindBin; use JSON::XS; ## name Allowed BadModules failing ## parms { allowed_modules => 'AnyEvent FindBin JSON::XS' }; ## failures 3 ## cut use Any::Moose; use CGI; use IO::Socket::INET6; SplitQuotedPattern.run100644001750001750 146014734076151 24664 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name SplitStrings ## failures 4 ## cut split 'foo', $bar; split "foo", $bar; split q{foo}, $bar; split qq{foo}, $bar; ## name SplitSpace ## failures 0 ## cut split ' ', $bar; split " ", $bar; split q{ }, $bar; split qq{ }, $bar; ## name SplitRegex ## failures 0 ## cut split /foo/, $bar; split m/foo/, $bar; split qr/foo/, $bar; split /./, $bar; split / /, $bar; split //, $bar; ## name SplitEmpty ## failures 0 ## cut split '', $bar; split "", $bar; split q{}, $bar; split qq{}, $bar; split //, $bar; split m//, $bar; split qr//, $bar; ## name SplitUnquoted ## failures 4 ## cut split $foo, $bar; split foo, $bar; split 42, $bar; split @args; ## name SplitUnquotedAllowed ## parms { allow_unquoted_patterns => '1' } ## failures 0 ## cut split $foo, $bar; split foo, $bar; split 42, $bar; split @args; BarewordFilehandles.run100644001750001750 635314734076151 24763 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name BarewordOpen ## failures 12 ## cut open FILE; open FILE, "<$filename"; open FILE, '<', $filename; open(FILE, '<', $filename); open FH, '>', $some_file; open FH, '>', $some_file or die; open(FH, '>', $some_file); open(FH, '>', $some_file) or die; open FH, ">$some_file"; open FH, ">$some_file" or die; open(FH, ">$some_file"); open(FH, ">$some_file") or die; ## name BarewordOpenBuiltin ## failures 0 ## cut open STDOUT; open STDIN, "<$filename"; open(STDERR, '>', $filename); open STDIN, '>', $some_file; open STDIN, '>', $some_file or die; open(STDIN, '>', $some_file); open(STDIN, '>', $some_file) or die; open STDIN, ">$some_file"; open STDIN, ">$some_file" or die; open(STDIN, ">$some_file"); open(STDIN, ">$some_file") or die; open STDOUT, '>', $some_file; open STDOUT, '>', $some_file or die; open(STDOUT, '>', $some_file); open(STDOUT, '>', $some_file) or die; open STDOUT, ">$some_file"; open STDOUT, ">$some_file" or die; open(STDOUT, ">$some_file"); open(STDOUT, ">$some_file") or die; open STDERR, '>', $some_file; open STDERR, '>', $some_file or die; open(STDERR, '>', $some_file); open(STDERR, '>', $some_file) or die; open STDERR, ">$some_file"; open STDERR, ">$some_file" or die; open(STDERR, ">$some_file"); open(STDERR, ">$some_file") or die; ## name VariableOpen ## failures 0 ## cut open $fh, '>', $some_file; open $fh, '>', $some_file or die; open($fh, '>', $some_file); open($fh, '>', $some_file) or die; open my $fh, '>', $some_file; open my $fh, '>', $some_file or die; open(my $fh, '>', $some_file); open(my $fh, '>', $some_file) or die; open our $fh, '>', $some_file; open our $fh, '>', $some_file or die; open(our $fh, '>', $some_file); open(our $fh, '>', $some_file) or die; open local $foo{fh}, '>', $some_file; open local $foo{fh}, '>', $some_file or die; open(local $foo{fh}, '>', $some_file); open(local $foo{fh}, '>', $some_file) or die; open local $foo{fh}, ">$some_file"; open local $foo{fh}, ">$some_file" or die; open(local $foo{fh}, ">$some_file"); open(local $foo{fh}, ">$some_file") or die; open local *STDIN, '>', $some_file; open local *STDIN, '>', $some_file or die; open(local *STDIN, '>', $some_file); open(local *STDIN, '>', $some_file) or die; open local *STDIN, ">$some_file"; open local *STDIN, ">$some_file" or die; open(local *STDIN, ">$some_file"); open(local *STDIN, ">$some_file") or die; open local *STDOUT, '>', $some_file; open local *STDOUT, '>', $some_file or die; open(local *STDOUT, '>', $some_file); open(local *STDOUT, '>', $some_file) or die; open local *STDOUT, ">$some_file"; open local *STDOUT, ">$some_file" or die; open(local *STDOUT, ">$some_file"); open(local *STDOUT, ">$some_file") or die; open local *STDERR, '>', $some_file; open local *STDERR, '>', $some_file or die; open(local *STDERR, '>', $some_file); open(local *STDERR, '>', $some_file) or die; open local *STDERR, ">$some_file"; open local *STDERR, ">$some_file" or die; open(local *STDERR, ">$some_file"); open(local *STDERR, ">$some_file") or die; ## name BarewordPipe ## failures 6 ## cut pipe READ, my $write; pipe my $read, WRITE; pipe READ, WRITE; pipe(READ, WRITE); ## name BarewordPipeBuiltin ## failures 0 ## cut pipe DATA, my $write; ## name LexicalPipe ## failures 0 ## cut pipe my $read, my $write; pipe(my $read, my $write); PreferredAlternatives.run100644001750001750 121614734076151 25350 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name GoodModules ## failures 0 ## cut use Cpanel::JSON::XS; use Const::Fast; use Getopt::Long; use Getopt::Long::Descriptive; use JSON::MaybeXS; use JSON::PP; use List::SomeUtils; use List::Util; use List::UtilsBy; use Moo; use Moose; use ReadonlyX; ## name BadModules ## failures 5 ## cut use Getopt::Std; use JSON; use List::MoreUtils; use Mouse; use Readonly; ## name Allowed BadModules ## parms { allowed_modules => 'Getopt::Std JSON' }; ## failures 0 ## cut use Getopt::Std; use JSON; ## name Allowed BadModules failing ## parms { allowed_modules => 'Getopt::Std JSON' }; ## failures 3 ## cut use List::MoreUtils; use Mouse; use Readonly; IndirectObjectNotation.run100644001750001750 42114734076151 25431 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name IndirectCalls ## failures 4 ## cut my $foo = new Foo; my $foo = new Foo @args; my $bar = new $foo; my $bar = new $foo @args; ## name DirectCalls ## failures 0 ## cut my $foo = Foo->new; my $foo = Foo->new(@args); my $bar = $foo->new; my $bar = $foo->new(@args); LexicalForeachIterator.run100644001750001750 42714734076151 25416 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name UndeclaredIterator ## failures 2 ## cut for $foo (@bar) {} foreach $bar (@foo) {} ## name DeclaredIterator ## failures 0 ## cut for my $foo (@bar) {} foreach my $bar (@foo) {} ## name NoIterator ## failures 0 ## cut for (@bar) {} for ($foo = 0; $foo < 5; $foo++) {} PackageMatchesFilename.run100644001750001750 61014734076151 25326 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name MatchesFilename ## failures 0 ## filename path/to/My/Package.pm ## cut package My::Package; ## name MatchesEndFilename ## failures 0 ## filename path/to/My/Package.pm ## cut package Package; ## name NoMatchingFilename ## failures 1 ## filename path/to/My/Package.pm ## cut package MyPackage; ## name NotModule ## failures 0 ## filename path/to/My/File.t ## cut package MyFile; ConditionalDeclarations.run100644001750001750 40114734076151 25617 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name ConditionalDeclarations ## failures 3 ## cut my $foo = $bar if $baz; my ($foo, $bar) = @baz unless $abc; our $foo = $_ for @bar; ## name UnconditionalDeclarations ## failures 0 ## cut my $foo = $bar; $foo = $bar if $baz; our $bar = $baz ? 1 : 2; Community000755001750001750 014734076151 24043 5ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/PolicyEach.pm100644001750001750 372514734076151 25410 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::Each; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy'; our $VERSION = 'v1.0.4'; use constant DESC => 'each() called'; use constant EXPL => 'The each function may cause undefined behavior when operating on the hash while iterating. Use a foreach loop over the hash\'s keys or values instead.'; sub supported_parameters { () } sub default_severity { $SEVERITY_LOW } sub default_themes { 'community' } sub applies_to { 'PPI::Token::Word' } sub violates { my ($self, $elem) = @_; return () unless $elem eq 'each' and is_function_call $elem; return $self->violation(DESC, EXPL, $elem); } 1; =head1 NAME Perl::Critic::Policy::Community::Each - Don't use each to iterate through a hash =head1 DESCRIPTION The C function relies on an iterator internal to a hash (or array), which is the same iterator used by C and C. So deleting or adding hash elements during iteration, or just calling C or C on the hash, will cause undefined behavior and the code will likely break. This could occur even by passing the hash to other functions which operate on the hash. Instead, use a C loop iterating through the keys or values of the hash. while (my ($key, $value) = each %hash) { ... } # not ok foreach my $key (keys %hash) { my $value = $hash{$key}; ... } # ok foreach my $i (0..$#array) { my $elem = $array[$i]; ... } # ok =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L, L ConditionalImplicitReturn.run100644001750001750 76614734076151 26177 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name ImplicitConditional ## failures 1 ## cut sub foo { if ($foo) { return 1 } } ## name ImplicitConditionalNoReturn ## failures 0 ## cut sub foo { return if bar(); if ($foo) { bar() } } ## name NotLastStatement ## failures 0 ## cut sub foo { if ($foo) { return 1 } return 0 } ## name ConditionalWithElsif ## failures 1 ## cut sub foo { if ($foo) { return 1 } elsif ($bar) { return 0 } } ## name ConditionalWithElse ## failures 0 ## cut sub foo { if ($foo) { return 1 } else { return 0 } } ModPerl.pm100644001750001750 406214734076151 26105 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::ModPerl; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy'; our $VERSION = 'v1.0.4'; use constant DESC => 'Using mod_perl'; use constant EXPL => 'mod_perl is not designed for writing Perl web applications. Try a Plack-based framework (Web::Simple, Dancer2, Catalyst) or Mojolicious for a modern approach.'; sub supported_parameters { () } sub default_severity { $SEVERITY_HIGH } sub default_themes { 'community' } sub applies_to { 'PPI::Statement::Include' } my %modules = ( 'Apache' => 1, 'Apache::Constants' => 1, 'Apache::Registry' => 1, 'Apache::Request' => 1, 'Apache2::Const' => 1, 'Apache2::Request' => 1, 'ModPerl::Const' => 1, 'ModPerl::Registry' => 1, ); sub violates { my ($self, $elem) = @_; return $self->violation(DESC, EXPL, $elem) if exists $modules{$elem->module//''}; return (); } 1; =head1 NAME Perl::Critic::Policy::Community::ModPerl - Don't use mod_perl to write web applications =head1 DESCRIPTION L is an embedded Perl interpreter for the L web server. It allows you to dynamically configure and mod Apache. It is not a generally good solution for writing web applications. Frameworks using L (L, L, L) and L are much more flexible, powerful, and stable. A web application written in one of these frameworks can be deployed using a Perl HTTP server such as L or L; by proxy from Apache or nginx; or even run as if they were regular CGI scripts. =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L Threads.pm100644001750001750 353214734076151 26136 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::Threads; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy'; our $VERSION = 'v1.0.4'; use constant DESC => 'Using interpreter threads'; use constant EXPL => 'Interpreter threads are discouraged, they are not lightweight and fast as other threads may be. Try an event loop, forks.pm, or Parallel::Prefork.'; sub supported_parameters { () } sub default_severity { $SEVERITY_MEDIUM } sub default_themes { 'community' } sub applies_to { 'PPI::Statement::Include' } sub violates { my ($self, $elem) = @_; return $self->violation(DESC, EXPL, $elem) if $elem->pragma eq 'threads'; return (); } 1; =head1 NAME Perl::Critic::Policy::Community::Threads - Interpreter-based threads are officially discouraged =head1 DESCRIPTION Perl interpreter L are officially discouraged. They were created to emulate C in Windows environments, and are not fast or lightweight as one may expect. Non-blocking code or I/O can be easily parallelized by using an event loop such as L, L, or L. Blocking code is usually better parallelized by forking, which on Unix-like systems is fast and efficient. Modules such as L and L can make forking easier to work with, as well as forking modules for event loops such as L, L, or L. =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L DollarAB.pm100644001750001750 540314734076151 26163 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::DollarAB; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy'; our $VERSION = 'v1.0.4'; use constant DESC => 'Using $a or $b outside sort()'; use constant EXPL => '$a and $b are special package variables for use in sort() and related functions. Declaring them as lexicals like "my $a" may break sort(). Use different variable names.'; sub supported_parameters { ( { name => 'extra_pair_functions', description => 'Non-standard functions in which to allow $a and $b', behavior => 'string list', }, ) } sub default_severity { $SEVERITY_HIGH } sub default_themes { 'community' } sub applies_to { 'PPI::Token::Symbol' } my @sorters = qw(sort reduce pairgrep pairfirst pairmap pairwise); sub violates { my ($self, $elem) = @_; return () unless $elem->symbol eq '$a' or $elem->symbol eq '$b'; my %sorters_hash = map { ($_ => 1) } @sorters, keys %{$self->{_extra_pair_functions}}; my $found = $self->_find_sorter($elem, \%sorters_hash); return $self->violation(DESC, EXPL, $elem) unless $found; return (); } sub _find_sorter { my ($self, $elem, $sorters) = @_; my $outer = $elem->parent; $outer = $outer->parent until !$outer or $outer->isa('PPI::Structure::Block'); return '' unless $outer; # Find function or method call (assumes block/sub is first argument) my $function = $outer->previous_token; $function = $function->previous_token until !$function or ($function->isa('PPI::Token::Word') and $function =~ m/([^:]+)\z/ and exists $sorters->{$1}); return $self->_find_sorter($outer) unless $function; return $function; } 1; =head1 NAME Perl::Critic::Policy::Community::DollarAB - Don't use $a or $b as variable names outside sort =head1 DESCRIPTION The special variables C<$a> and C<$b> are reserved for C and similar functions which assign to them to iterate over pairs of values. These are global variables, and declaring them as lexical variables with C to use them outside this context can break usage of these functions. Use different names for your variables. my $a = 1; # not ok my $abc = 1; # ok sort { $a <=> $b } (3,2,1); # ok =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy can be configured to allow C<$a> and C<$b> in additional functions, by putting an entry in a C<.perlcriticrc> file like this: [Community::DollarAB] extra_pair_functions = pairfoo pairbar =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L OpenArgs.pm100644001750001750 425614734076151 26266 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::OpenArgs; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy'; our $VERSION = 'v1.0.4'; use constant DESC => 'open() called with less than 3 arguments'; use constant EXPL => 'The one- and two-argument forms of open() parse functionality from the filename, use the three-argument form instead.'; sub supported_parameters { () } sub default_severity { $SEVERITY_MEDIUM } sub default_themes { 'community' } sub applies_to { 'PPI::Token::Word' } sub violates { my ($self, $elem) = @_; return () unless $elem eq 'open' and is_function_call $elem; my @args = parse_arg_list $elem; if (@args < 3) { return () if @args == 2 and $args[1][0]->isa('PPI::Token::Quote') and $args[1][0]->string =~ /^(?:-\||\|-)\z/; return $self->violation(DESC, EXPL, $elem); } return (); } 1; =head1 NAME Perl::Critic::Policy::Community::OpenArgs - Always use the three-argument form of open =head1 DESCRIPTION The C function may be called in a two-argument form where the filename is parsed to determine the mode of opening, which may include piping input or output. (In the one-argument form, this filename is retrieved from a global variable, but the same magic is used.) This can lead to vulnerabilities if the filename is retrieved from user input or could begin or end with a special character. The three-argument form specifies the open mode as the second argument, so it is always distinct from the filename. open FILE; # not ok open my $fh, "<$filename"; # not ok open my $fh, '<', $filename; # ok This policy is similar to the core policy L, but additionally prohibits one-argument opens. =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L Wantarray.pm100600001750001750 432314734076151 26503 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::Wantarray; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy'; our $VERSION = 'v1.0.4'; use constant DESC => 'wantarray() called'; use constant EXPL => 'Context-sensitive functions lead to unexpected errors or vulnerabilities. Functions should explicitly return either a list or a scalar value.'; sub supported_parameters { () } sub default_severity { $SEVERITY_LOW } sub default_themes { 'community' } sub applies_to { 'PPI::Token::Word' } sub violates { my ($self, $elem) = @_; return () unless (($elem eq 'wantarray' or $elem->literal eq 'CORE::wantarray') and is_function_call $elem); return $self->violation(DESC, EXPL, $elem); } 1; =head1 NAME Perl::Critic::Policy::Community::Wantarray - Don't write context-sensitive functions using wantarray =head1 DESCRIPTION Context-sensitive functions, while one way to write functions that DWIM (Do What I Mean), tend to instead lead to unexpected behavior when the function is accidentally used in a different context, especially if the function's behavior changes significantly based on context. This also can lead to vulnerabilities when a function is intended to be used as a scalar, but is used in a list, such as a hash constructor or function parameter list. Instead, functions should be explicitly documented to return either a scalar value or a list, so there is no potential for confusion or vulnerability. return wantarray ? ('a','b','c') : 3; # not ok return CORE::wantarray ? ('a', 'b', 'c') : 3; # not ok return ('a','b','c'); # ok return 3; # ok sub get_stuff { return wantarray ? @things : \@things; } my $stuff = Stuff->new(stuff => get_stuff()); # oops! function will return a list! =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L WhileDiamondDefaultAssignment.run100644001750001750 324514734076151 26756 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name DefaultAssignment ## failures 4 ## cut while (<$fh>) {} while () {} while (<>) {} while (<<>>) {} ## name DefaultAssignmentModifier ## failures 4 ## cut 1 while <$fh>; 1 while ; 1 while <>; 1 while <<>>; ## name DefaultAssignmentFor ## failures 4 ## cut for (;<$fh>;) {} for (;;) {} for (;<>;) {} for (;<<>>;) {} ## name DefaultAssignmentReadline ## failures 8 ## cut while (readline $fh) {} while (readline($fh)) {} while (readline DATA) {} while (readline(DATA)) {} 1 while readline $fh; 1 while readline($fh); 1 while readline DATA; 1 while readline(DATA); ## name DefaultAssignmentReaddir ## failures 8 ## cut while (readdir $dh) {} while (readdir($dh)) {} while (readdir DIR) {} while (readdir(DIR)) {} 1 while readdir $dh; 1 while readdir($dh); 1 while readdir DIR; 1 while readdir(DIR); ## name DefaultAssignmentEach ## failures 4 ## cut while (each %hash) {} while (each(%hash)) {} 1 while each %hash; 1 while each(%hash); ## name ExplicitAssignment ## failures 0 ## cut while (my $line = <$fh>) {} for (;my $line = <$fh>;) {} 1 while $line = <$fh>; while (my $line = ) {} for (;my $line = ;) {} 1 while $line = ; while (my $line = <>) {} for (;my $line = <>;) {} 1 while $line = <>; while (my $line = <<>>) {} for (;my $line = <<>>;) {} 1 while $line = <<>>; while (my $line = readline $fh) {} while (my $line = readline($fh)) {} 1 while $line = readline $fh; 1 while $line = readline($fh); while (my $dir = readdir $dh) {} while (my $dir = readdir($dh)) {} 1 while $dir = readdir $dh; 1 while $dir = readdir($dh); while (my $key = each %hash) {} while (my $key = each(%hash)) {} 1 while $key = each %hash; 1 while $key = each(%hash); LoopOnHash.pm100644001750001750 312214734076151 26551 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::LoopOnHash; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy::Variables::ProhibitLoopOnHash'; our $VERSION = 'v1.0.4'; sub default_severity { $SEVERITY_HIGH } sub default_themes { 'community' } 1; =head1 NAME Perl::Critic::Policy::Community::LoopOnHash - Don't loop over hashes =head1 DESCRIPTION It's possible to loop over a hash as if it was a list, which results in alternating between the keys and values of the hash. Often, the intent was instead to loop over either the keys or the values of the hash. foreach my $foo (%hash) { ... } # not ok action() for %hash; # not ok foreach my $foo (keys %hash) { ... } # ok action() for values %hash; # ok If you intended to loop over alternating keys and values, you can make this intent clear by first copying them to an array: foreach my $key_or_value (@{[%hash]}) { ... } foreach my $key_or_value (my @dummy = %hash) { ... } This policy is a subclass of the policy L, and performs the same function but in the C theme. =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L Prototypes.pm100644001750001750 651114734076151 26734 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::Prototypes; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy'; use version; our $VERSION = 'v1.0.4'; use constant DESC => 'Using function prototypes'; use constant EXPL => 'Function prototypes (sub foo ($@) { ... }) will usually not do what you want. Omit the prototype, or use signatures instead.'; sub supported_parameters { ( { name => 'signature_enablers', description => 'Non-standard modules to recognize as enabling signatures', behavior => 'string list', }, ) } sub default_severity { $SEVERITY_MEDIUM } sub default_themes { 'community' } sub applies_to { 'PPI::Document' } sub violates { my ($self, $elem) = @_; # Check if signatures are enabled my $includes = $elem->find('PPI::Statement::Include') || []; foreach my $include (@$includes) { next unless $include->type eq 'use'; return () if $include->version and version->parse($include->version) >= version->parse('v5.36'); return () if $include->pragma eq 'feature' and $include =~ m/\bsignatures\b/; return () if $include->pragma eq 'experimental' and $include =~ m/\bsignatures\b/; return () if $include->module eq 'Mojo::Base' and $include =~ m/-signatures\b/; return () if $include->module eq 'Mojolicious::Lite' and $include =~ m/-signatures\b/; return () if exists $self->{_signature_enablers}{$include->module}; } my $prototypes = $elem->find('PPI::Token::Prototype') || []; my @violations; foreach my $prototype (@$prototypes) { # Empty prototypes and prototypes containing & can be useful next if $prototype->prototype eq '' or $prototype->prototype =~ /&/; push @violations, $self->violation(DESC, EXPL, $prototype); } return @violations; } 1; =head1 NAME Perl::Critic::Policy::Community::Prototypes - Don't use function prototypes =head1 DESCRIPTION Function prototypes are primarily a hint to the Perl parser for parsing the function's argument list. They are not a way to validate or count the arguments passed to the function, and will cause confusion if used this way. Often, the prototype can simply be left out, but see L for a more modern method of declaring arguments. sub foo ($$) { ... } # not ok sub foo { ... } # ok use feature 'signatures'; sub foo ($bar, $baz) { ... } # ok use experimental 'signatures'; sub foo ($bar, $baz) { ... } # ok This policy is similar to the core policy L, but additionally ignores files using the C feature (which is also enabled by a C declaration of perl version 5.36 or higher), and allows empty prototypes and prototypes containing C<&>, as these are often useful for structural behavior. =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy can be configured to recognize additional modules as enabling the C feature, by putting an entry in a C<.perlcriticrc> file like this: [Community::Prototypes] signature_enablers = MyApp::Base =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L MultidimensionalArrayEmulation.run100600001750001750 131514734076151 27232 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/t/Community## name ScalarAccess ## failures 0 ## cut $foo{bar}; $foo{'bar'}; $$foo{ bar }; $foo{'bar,baz'}; $foo{bar(1,2)}; $foo{bar 1, 2}; ## name Slices ## failures 0 ## cut @foo {'bar','baz'}; @{foo}{qw(bar baz)}; @{$foo{bar}}{a => 'b'}; @{@foo[0]}{'a','b'}; @$foo{'a','b'}; $foo->@{'a','b'}; %foo{'bar','baz'}; %{foo}{'bar','baz'}; %{$foo{bar}}{'a','b'}; %{@foo[0]}{'a','b'}; %$foo{'a','b'}; $foo->%{'a','b'}; ## name MAE ## failures 10 ## cut $foo{'bar','baz'}; ${foo} {qw(bar baz)}; $foo{bar}{a => 'b'}; ${@foo[0]}{'a','b'}; $$foo {'a','b'}; {1,2}->{'bar','baz'}; foo->[2]{'bar','baz'}; $foo{bar (1),2}; $foo{1,bar 2}; $foo{bar, 2}; ## name Nested ## failures 3 ## cut $foo->{ $bar->{'a','b'} => $baz->{qw(a b)} }; EmptyReturn.pm100644001750001750 677614734076151 27057 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::EmptyReturn; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy'; use List::Util 'any'; use Perl::Critic::Community::Utils qw(is_empty_return is_structural_block); our $VERSION = 'v1.0.4'; use constant DESC => 'return called with no arguments'; use constant EXPL => 'return with no arguments may return either undef or an empty list depending on context. This can be surprising for the same reason as other context-sensitive returns. Return undef or the empty list explicitly.'; sub supported_parameters { () } sub default_severity { $SEVERITY_LOWEST } sub default_themes { 'community' } sub applies_to { 'PPI::Statement::Sub' } sub violates { my ($self, $elem) = @_; my $block = $elem->block || return (); my $returns = $block->find(sub { my ($elem, $child) = @_; # Don't search in blocks unless we know they are structural if ($child->isa('PPI::Structure::Block')) { return undef unless is_structural_block($child); } return 1 if $child->isa('PPI::Token::Word') and $child eq 'return'; return 0; }); # Return a violation for each empty return, if any non-empty return is present if ($returns and any { !is_empty_return($_) } @$returns) { return map { $self->violation(DESC, EXPL, $_) } grep { is_empty_return($_) } @$returns; } return (); } 1; =head1 NAME Perl::Critic::Policy::Community::EmptyReturn - Don't use return with no arguments =head1 DESCRIPTION Context-sensitive functions, while one way to write functions that DWIM (Do What I Mean), tend to instead lead to unexpected behavior when the function is accidentally used in a different context, especially if the function's behavior changes significantly based on context. This also can lead to vulnerabilities when a function is intended to be used as a scalar, but is used in a list, such as a hash constructor or function parameter list. C with no arguments will return either C or an empty list depending on context. Instead, return the appropriate value explicitly. return; # not ok return (); # ok return undef; # ok sub get_stuff { return unless @things; return join(' ', @things); } my %stuff = ( one => 1, two => get_stuff(), # oops! function returns empty list if @things is empty three => 3, ); Empty returns are permitted by this policy if the subroutine contains no explicit return values, indicating it is intended to be used in void context. =head1 CAVEATS This policy currently only checks return statements in named subroutines, anonymous subroutines are not checked. Also, return statements within blocks, other than compound statements like C and C, are not considered when determining if a function is intended to be used in void context. Any non-empty return will cause empty returns within the same subroutine to report violations, even though in list context, C and C are functionally equivalent. It is recommended to explicitly specify an empty list return with C in a function that intends to return list context. =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L POSIXImports.pm100644001750001750 370514734076151 27026 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::POSIXImports; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy'; our $VERSION = 'v1.0.4'; use constant DESC => 'Using POSIX.pm without an explicit import list'; use constant EXPL => 'Using the POSIX module without specifying an import list results in importing hundreds of symbols. Import the functions or constants you want explicitly, or prevent the import with ().'; sub supported_parameters { () } sub default_severity { $SEVERITY_LOW } sub default_themes { 'community' } sub applies_to { 'PPI::Statement::Include' } sub violates { my ($self, $elem) = @_; return $self->violation(DESC, EXPL, $elem) if ($elem->type // '') eq 'use' and ($elem->module // '') eq 'POSIX' and !$elem->arguments; return (); } 1; =head1 NAME Perl::Critic::Policy::Community::POSIXImports - Don't use POSIX without specifying an import list =head1 DESCRIPTION The L module imports hundreds of symbols (functions and constants) by default for backwards compatibility reasons. To avoid this, and to assist in finding where functions have been imported from, specify the symbols you want to import explicitly in the C statement. Alternatively, specify an empty import list with C to avoid importing any symbols, and fully qualify the functions or constants, such as C. use POSIX; # not ok use POSIX (); # ok use POSIX 'fcntl'; # ok use POSIX qw(O_APPEND O_CREAT O_EXCL O_RDONLY O_RDWR O_WRONLY); # ok =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L StrictWarnings.pm100644001750001750 1007714734076151 27547 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::StrictWarnings; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use Perl::Critic::Utils::Constants qw(@STRICT_EQUIVALENT_MODULES @WARNINGS_EQUIVALENT_MODULES); use parent 'Perl::Critic::Policy'; use version; our $VERSION = 'v1.0.4'; use constant DESC => 'Missing strict or warnings'; use constant EXPL => 'The strict and warnings pragmas are important to avoid common pitfalls and deprecated/experimental functionality. Make sure each script or module contains "use strict; use warnings;" or a module that does this for you.'; sub supported_parameters { ( { name => 'extra_importers', description => 'Non-standard modules to recognize as importing strict and warnings', behavior => 'string list', }, ) } sub default_severity { $SEVERITY_HIGH } sub default_themes { 'community' } sub applies_to { 'PPI::Document' } my @incomplete_importers = qw(common::sense sanity); sub violates { my ($self, $elem) = @_; my $includes = $elem->find('PPI::Statement::Include') || []; # Add importers from Perl::Critic core my %strict_importers = map { ($_ => 1) } @STRICT_EQUIVALENT_MODULES; my %warnings_importers = map { ($_ => 1) } @WARNINGS_EQUIVALENT_MODULES; # Remove incomplete importers if added delete $strict_importers{$_} for @incomplete_importers; delete $warnings_importers{$_} for @incomplete_importers; # Add extra importers $strict_importers{$_} = $warnings_importers{$_} = 1 foreach keys %{$self->{_extra_importers}}; my ($has_strict, $has_warnings); foreach my $include (@$includes) { if ($include->pragma) { $has_strict = 1 if $include->pragma eq 'strict'; $has_warnings = 1 if $include->pragma eq 'warnings'; } if ($include->type//'' eq 'use') { $has_strict = 1 if $include->version and version->parse($include->version) >= version->parse('v5.12'); $has_strict = 1 if defined $include->module and exists $strict_importers{$include->module}; $has_warnings = 1 if $include->version and version->parse($include->version) >= version->parse('v5.36'); $has_warnings = 1 if defined $include->module and exists $warnings_importers{$include->module}; } return () if $has_strict and $has_warnings; } return $self->violation(DESC, EXPL, $elem); } 1; =head1 NAME Perl::Critic::Policy::Community::StrictWarnings - Always use strict and warnings, or a module that imports these =head1 DESCRIPTION The L and L pragmas help avoid many common pitfalls such as misspellings, scoping issues, and performing operations on undefined values. Warnings can also alert you to deprecated or experimental functionality. The pragmas may either be explicitly imported with C, or indirectly through a number of importer modules such as L or L. L is also enabled automatically with a C declaration of perl version 5.12 or higher, as is L with a C declaration of 5.36 or higher. use strict; use warnings; use Moose; use 5.012; use warnings; use 5.036; This policy is similar to the core policies L and L, but combines them into one policy in the C theme. The default modules recognized as importing L and L are defined by the same constants as the core policies, L. To define additional modules, see L. =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy can be configured to recognize additional modules as importers of L and L, by putting an entry in a C<.perlcriticrc> file like this: [Community::StrictWarnings] extra_importers = MyApp::Class MyApp::Role =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L WarningsSwitch.pm100644001750001750 351514734076151 27517 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::WarningsSwitch; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy'; our $VERSION = 'v1.0.4'; use constant DESC => 'Using -w switch'; use constant EXPL => 'Don\'t use -w (or -W), it\'s too eager. use warnings; instead.'; sub supported_parameters { () } sub default_severity { $SEVERITY_LOW } sub default_themes { 'community' } sub applies_to { 'PPI::Document' } sub violates { my ($self, $elem) = @_; my $shebang = $elem->first_token; return () unless $shebang->isa('PPI::Token::Comment') and $shebang->content =~ m/^#!/; return $self->violation(DESC, EXPL, $elem) if $shebang->content =~ m/\h-[a-zA-Z]*[wW]/; return (); } 1; =head1 NAME Perl::Critic::Policy::Community::WarningsSwitch - Scripts should not use the -w switch on the shebang line =head1 DESCRIPTION The C<-w> switch enables warnings globally in a perl program, including for any modules that did not explicitly enable or disable any warnings. The C<-W> switch enables warnings even for modules that explicitly disabled them. The primary issue with this is enabling warnings for code that you did not write. Some of these modules may not be designed to run with warnings enabled, but still work fine. Instead, use L within your own code only. #!/usr/bin/perl -w # not ok #!/usr/bin/perl -W # not ok use warnings; # ok =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L, L ArrayAssignAref.pm100644001750001750 302214734076151 27557 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::ArrayAssignAref; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy::Plicease::ProhibitArrayAssignAref'; our $VERSION = 'v1.0.4'; sub default_severity { $SEVERITY_MEDIUM } sub default_themes { 'community' } 1; =head1 NAME Perl::Critic::Policy::Community::ArrayAssignAref - Don't assign an anonymous arrayref to an array =head1 DESCRIPTION A common mistake is to assign values to an array but use arrayref brackets C<[]> rather than parentheses C<()>. This results in the array containing one element, an arrayref, which is usually unintended. If intended, the arrayref brackets can be wrapped in parentheses for clarity. @array = []; # not ok @array = [1, 2, 3]; # not ok @array = ([1, 2, 3]); # ok This policy is a subclass of L, which is a fork of the L policy L, and performs the same function but in the C theme. =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L, L OverloadOptions.pm100644001750001750 771114734076151 27676 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::OverloadOptions; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy'; our $VERSION = 'v1.0.4'; use constant DESC => 'Using overload.pm without a boolean overload or fallback'; use constant EXPL => 'When using overload.pm to define overloads for an object class, always define an overload on "bool" explicitly and set the fallback option. This prevents objects from autogenerating a potentially surprising boolean overload, and causes operators for which overloads can\'t be autogenerated to act on the object as they normally would.'; sub supported_parameters { () } sub default_severity { $SEVERITY_HIGH } sub default_themes { 'community' } sub applies_to { 'PPI::Statement::Include' } sub violates { my ($self, $elem) = @_; return () unless ($elem->type // '') eq 'use' and ($elem->module // '') eq 'overload'; my @args = $elem->arguments; my ($has_bool, $has_fallback); my @options; while (@args) { my $arg = shift @args; # use overload qw(...); if ($arg->isa('PPI::Token::QuoteLike::Words')) { push @options, $arg->literal; # use overload 'foo', 1; } elsif ($arg->isa('PPI::Token::Quote')) { push @options, $arg->string; # use overload foo => 1; } elsif ($arg->isa('PPI::Token::Word') or $arg->isa('PPI::Token::Number')) { push @options, $arg->literal; # unpack lists and expressions } elsif ($arg->isa('PPI::Structure::List') or $arg->isa('PPI::Statement::Expression')) { unshift @args, $arg->schildren; } } # use overload; or use overload (); return () unless @options; foreach my $i (0..$#options) { my $item = $options[$i]; if ($item eq 'fallback' and defined $options[$i+1] and $options[$i+1] ne 'undef') { $has_fallback = 1; } elsif ($item eq 'bool') { $has_bool = 1; } } return $self->violation(DESC, EXPL, $elem) unless $has_bool and $has_fallback; return (); } 1; =head1 NAME Perl::Critic::Policy::Community::OverloadOptions - Don't use overload without specifying a bool overload and enabling fallback =head1 DESCRIPTION The L module allows an object class to specify behavior for an object used in various operations. However, when activated it enables additional behavior by default: it L overload behavior for operators that are not specified, and if it cannot autogenerate an overload for an operator, using that operator on the object will throw an exception. An autogenerated boolean overload can lead to surprising behavior where an object is considered "false" because of another overloaded value. For example, if a class overloads stringification to return the object's name, but the object's name is C<0>, then the object will be considered false due to an autogenerated overload using the boolean value of the string. This is rarely desired behavior, and if needed, it can be set as an explicit boolean overload. Without setting the C option, any operators that cannot be autogenerated from defined overloads will result in an exception when used. By setting C to C<1>, the operator will instead fall back to standard behavior as if no overload was defined, which is generally the expected behavior when only overloading a few operations. use overload '""' => sub { $_[0]->name }; # not ok use overload '""' => sub { $_[0]->name }, bool => sub { 1 }; # not ok use overload '""' => sub { $_[0]->name }, fallback => 1; # not ok use overload '""' => sub { $_[0]->name }, bool => sub { 1 }, fallback => 1; # ok =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L AmpersandSubCalls.pm100644001750001750 325614734076151 30112 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::AmpersandSubCalls; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy::Subroutines::ProhibitAmpersandSigils'; our $VERSION = 'v1.0.4'; sub default_severity { $SEVERITY_HIGH } sub default_themes { 'community' } 1; =head1 NAME Perl::Critic::Policy::Community::AmpersandSubCalls - Don't use & to call subroutines =head1 DESCRIPTION Ampersands (C<&>) were once needed to call subroutines, but in modern Perl they are not only unnecessary but actually change the behavior from what you may expect. Calling a subroutine with an ampersand ignores the subroutine's prototype if any, which may change what arguments the subroutine receives. Additionally, calling a subroutine as C<&foo;> with no arguments will pass on the contents of C<@_> from the current subroutine, which may be quite surprising. Unless used intentionally for this behavior, the ampersand should simply be omitted. my $value = &foo(); # not ok my $sum = &foo(1,2); # not ok my $value = foo(); # ok my $sum = foo 1,2; # ok This policy is a subclass of the core policy L, and performs the same function but in the C theme. =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L DeprecatedFeatures.pm100644001750001750 4001114734076151 30314 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::DeprecatedFeatures; use strict; use warnings; use List::Util 'any', 'none'; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy'; our $VERSION = 'v1.0.4'; sub supported_parameters { () } sub default_severity { $SEVERITY_HIGH } sub default_themes { 'community' } sub applies_to { 'PPI::Element' } my %features = ( ':=' => 'Use of := as an empty attribute list is deprecated in perl v5.12.0, use = alone.', '$[' => 'Use of $[ is deprecated in perl v5.12.0. See Array::Base and String::Base.', '/\\C/' => 'Use of the \\C character class in regular expressions is deprecated in perl v5.20.0. To examine a string\'s UTF-8-encoded byte representation, encode it to UTF-8.', '?PATTERN?' => 'Use of ? as a match regex delimiter without an initial m is deprecated in perl v5.14.0. Use m?PATTERN? instead.', 'autoderef' => 'Use of each/keys/pop/push/shift/splice/unshift/values on a reference is an experimental feature that is removed in perl v5.24.0. Dereference the array or hash to use these functions on it.', 'Bare here-doc' => 'Use of bare << to create a here-doc with an empty string terminator is deprecated in perl 5. Use a quoted empty string like <<\'\'.', 'chdir(\'\')' => 'Use of chdir(\'\') or chdir(undef) to chdir home is deprecated in perl v5.8.0. Use chdir() instead.', 'defined on array/hash' => 'Use of defined() on an array or hash is deprecated in perl v5.6.2. The array or hash can be tested directly to check for non-emptiness: if (@foo) { ... }', 'do SUBROUTINE(LIST)' => 'Use of do to call a subroutine is deprecated in perl 5.', 'NBSP in \\N{...}' => 'Use of the "no-break space" character in character names is deprecated in perl v5.22.0.', 'POSIX character function' => 'Several character matching functions in POSIX.pm are deprecated in perl v5.20.0: isalnum, isalpha, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isspace, isupper, and isxdigit. Regular expressions are a more portable and correct way to test character strings.', 'POSIX::tmpnam()' => 'The tmpnam() function from POSIX is deprecated in perl v5.22.0. Use File::Temp instead.', 'qw(...) as parentheses' => 'Use of qw(...) as parentheses is deprecated in perl v5.14.0. Wrap the list in literal parentheses when required, such as in a foreach loop.', 'require ::Foo::Bar' => 'Bareword require starting with a double colon is an error in perl v5.26.0.', 'UNIVERSAL->import()' => 'The method UNIVERSAL->import() (or passing import arguments to "use UNIVERSAL") is deprecated in perl v5.12.0.', ); my %posix_deprecated = map { ($_ => 1, "POSIX::$_" => 1) } qw(isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit); my %autoderef_functions = map { ($_ => 1) } qw(each keys pop push shift splice unshift values); sub _violation { my ($self, $feature, $elem) = @_; my $desc = "$feature is deprecated"; my $expl = $features{$feature} // "$feature is deprecated or removed from recent versions of Perl."; return $self->violation($desc, $expl, $elem); } sub violates { my ($self, $elem) = @_; my $next; my $prev; my $parent; my @args; my @violations; if ($elem->isa('PPI::Statement')) { if ($elem->isa('PPI::Statement::Include')) { # use UNIVERSAL ...; if ($elem->type eq 'use' and defined $elem->module and $elem->module eq 'UNIVERSAL') { my @args = $elem->arguments; if (!@args or !$args[0]->isa('PPI::Structure::List') or $args[0]->schildren) { push @violations, $self->_violation('UNIVERSAL->import()', $elem); } } # require ::Foo::Bar if (defined $elem->module and $elem->module =~ m/^::/) { push @violations, $self->_violation('require ::Foo::Bar', $elem); } } } elsif ($elem->isa('PPI::Token')) { if ($elem->isa('PPI::Token::Symbol')) { # $[ if ($elem eq '$[') { push @violations, $self->_violation('$[', $elem); } } elsif ($elem->isa('PPI::Token::Operator')) { # := if ($elem eq ':' and $next = $elem->next_sibling and $next->isa('PPI::Token::Operator') and $next eq '=') { push @violations, $self->_violation(':=', $elem); # ?PATTERN? - PPI parses this as multiple ? operators } elsif ($elem eq '?' and $parent = $elem->parent and $parent->isa('PPI::Statement')) { $next = $elem->snext_sibling; until (!$next or ($next->isa('PPI::Token::Operator') and $next eq '?')) { $next = $next->snext_sibling; } # If the statement has a : operator, this is probably a ternary operator. # PPI also tends to detect the : as a loop label. if ($next and none { ($_->isa('PPI::Token::Operator') and $_ eq ':') or $_->isa('PPI::Token::Label') } $parent->schildren) { push @violations, $self->_violation('?PATTERN?', $elem); } # Bare here-doc - differentiate this from the legitimate << operator } elsif ($elem eq '<<' and (!($next = $elem->snext_sibling) or ($next->isa('PPI::Token::Operator') and $next ne '~' and $next ne '!' and $next ne '+' and $next ne '-') or ($next->isa('PPI::Token::Structure') and $next ne '(' and $next ne '{' and $next ne '['))) { push @violations, $self->_violation('Bare here-doc', $elem); } } elsif ($elem->isa('PPI::Token::Word')) { # UNIVERSAL->import() if ($elem eq 'UNIVERSAL' and $next = $elem->snext_sibling and $next->isa('PPI::Token::Operator') and $next eq '->' and $next = $next->snext_sibling and $next->isa('PPI::Token::Word') and $next eq 'import') { push @violations, $self->_violation('UNIVERSAL->import()', $next); # for $x qw(...) } elsif (($elem eq 'for' or $elem eq 'foreach') and !$elem->sprevious_sibling) { $next = $elem->snext_sibling; until (!$next or $next->isa('PPI::Structure::List') or $next->isa('PPI::Token::QuoteLike::Words')) { $next = $next->snext_sibling; } if ($next and $next->isa('PPI::Token::QuoteLike::Words')) { push @violations, $self->_violation('qw(...) as parentheses', $next); } # do SUBROUTINE(LIST) } elsif ($elem eq 'do' and $next = $elem->snext_sibling) { if ((($next->isa('PPI::Token::Word') and is_function_call $next) or ($next->isa('PPI::Token::Symbol') and ($next->raw_type eq '&' or $next->raw_type eq '$'))) and ($next = $next->snext_sibling and $next->isa('PPI::Structure::List'))) { push @violations, $self->_violation('do SUBROUTINE(LIST)', $elem); } # avoid false positives for method calls } elsif (!($prev = $elem->sprevious_sibling) or !$prev->isa('PPI::Token::Operator') or $prev ne '->') { # POSIX character function or POSIX::tmpnam() if (exists $posix_deprecated{$elem} or $elem eq 'tmpnam' or $elem eq 'POSIX::tmpnam') { my $is_posix = $elem =~ m/^POSIX::/ ? 1 : 0; (my $function_name = $elem) =~ s/^POSIX:://; unless ($is_posix) { my $includes = $elem->document->find('PPI::Statement::Include') || []; foreach my $stmt (grep { ($_->module // '') eq 'POSIX' } @$includes) { my @args = $stmt->arguments; $is_posix = 1 if !@args or any { $_ =~ m/\b\Q$function_name\E\b/ } @args; } } if ($is_posix) { push @violations, $self->_violation('POSIX::tmpnam()', $elem) if $function_name eq 'tmpnam'; push @violations, $self->_violation('POSIX character function', $elem) if exists $posix_deprecated{$elem}; } # defined array/hash } elsif ($elem eq 'defined' and $next = $elem->snext_sibling) { $next = $next->schild(0) if $next->isa('PPI::Structure::List'); if ($next and $next->isa('PPI::Token::Symbol') and ($next->raw_type eq '@' or $next->raw_type eq '%') and $next->raw_type eq $next->symbol_type) { push @violations, $self->_violation('defined on array/hash', $elem); } # autoderef } elsif (exists $autoderef_functions{$elem} and $next = $elem->snext_sibling) { $next = $next->schild(0) if $next->isa('PPI::Structure::List'); $next = $next->schild(0) if $next and $next->isa('PPI::Statement::Expression'); if ($next and $next->isa('PPI::Token::Symbol') and $next->raw_type eq '$') { my $is_postderef; until (!$next or ($next->isa('PPI::Token::Structure') and $next eq ';') or ($next->isa('PPI::Token::Operator') and $next eq ',')) { $next = $next->snext_sibling; if ($next and $next->isa('PPI::Token::Cast') and ($next eq '@*' or $next eq '%*')) { $is_postderef = 1; last; } } push @violations, $self->_violation('autoderef', $elem) unless $is_postderef; } } elsif ($elem eq 'chdir' and $next = $elem->snext_sibling) { $next = $next->schild(0) if $next->isa('PPI::Structure::List'); $next = $next->schild(0) if $next and $next->isa('PPI::Statement::Expression'); if ($next and (($next->isa('PPI::Token::Quote') and !length $next->string) or ($next->isa('PPI::Token::Word') and $next eq 'undef'))) { push @violations, $self->_violation('chdir(\'\')', $elem); } } } } elsif ($elem->isa('PPI::Token::Regexp')) { # ?PATTERN? if ($elem->isa('PPI::Token::Regexp::Match') and ($elem->get_delimiters)[0] eq '??' and $elem !~ m/^m/) { push @violations, $self->_violation('?PATTERN?', $elem); } if (!$elem->isa('PPI::Token::Regexp::Transliterate')) { push @violations, $self->_violates_interpolated($elem); } } elsif ($elem->isa('PPI::Token::HereDoc')) { # Bare here-doc if ($elem eq '<<') { push @violations, $self->_violation('Bare here-doc', $elem); } } elsif ($elem->isa('PPI::Token::QuoteLike')) { if ($elem->isa('PPI::Token::QuoteLike::Regexp') or $elem->isa('PPI::Token::QuoteLike::Backtick') or $elem->isa('PPI::Token::QuoteLike::Command')) { push @violations, $self->_violates_interpolated($elem); } } elsif ($elem->isa('PPI::Token::Quote')) { if ($elem->isa('PPI::Token::Quote::Double') or $elem->isa('PPI::Token::Quote::Interpolate')) { push @violations, $self->_violates_interpolated($elem); } } } return @violations; } sub _violates_interpolated { my ($self, $elem) = @_; my @violations; # NBSP in \N{...} my $contents; if ($elem->isa('PPI::Token::Regexp') or $elem->isa('PPI::Token::QuoteLike::Regexp')) { $contents = $elem->get_match_string; # /\C/ push @violations, $self->_violation('/\\C/', $elem) if $contents =~ m/(?isa('PPI::Token::Quote')) { $contents = $elem->string; } else { # Backticks and qx elements have no contents method $contents = $elem; } push @violations, $self->_violation('NBSP in \\N{...}', $elem) if $contents =~ m/\\N\{[^}]*\x{a0}[^}]*\}/; return @violations; } 1; =head1 NAME Perl::Critic::Policy::Community::DeprecatedFeatures - Avoid features that have been deprecated or removed from Perl =head1 DESCRIPTION While L will expose usage of deprecated or removed features when a modern perl is used, this policy will detect such features in use regardless of perl version, to assist in keeping your code modern and forward-compatible. =head1 FEATURES =head2 := Because the whitespace between an attribute list and assignment operator is not significant, it was possible to specify assignment to a variable with an empty attribute list with a construction like C. This is deprecated in perl v5.12.0 to allow the possibility of a future C<:=> operator. Avoid the issue by either putting whitespace between the C<:> and C<=> characters or simply omitting the empty attribute list. =head2 $[ The magic L variable was used in very old perls to determine the index of the first element of arrays or the first character in substrings, and also allow modifying this value. It was discouraged from the start of Perl 5, its functionality changed in v5.10.0, deprecated in v5.12.0, re-implemented as L.pm in v5.16.0, and it is essentially a synonym for C<0> under C or C. While it is probably a bad idea in general, the modules L and L can now be used to replace this functionality. =head2 /\C/ The C<\C> regular expression character class would match a single byte of the internal representation of the string, which was dangerous because it violated the logical character abstraction of Perl strings, and substitutions using it could result in malformed UTF-8 sequences. It was deprecated in perl v5.20.0 and removed in perl v5.24.0. Instead, explicitly encode the string to UTF-8 using L to examine its UTF-8-encoded byte representation. =head2 ?PATTERN? The C regex match syntax is deprecated in perl v5.14.0 and removed in perl v5.22.0. Use C instead. =head2 autoderef An experimental feature was introduced in perl v5.14.0 to allow calling various builtin functions (which operate on arrays or hashes) on a reference, which would automatically dereference the operand. This led to ambiguity when passed objects that overload both array and hash dereferencing, and so was removed in perl v5.24.0. Instead, explicitly dereference the reference when calling these functions. The functions affected are C, C, C, C, C, C, C, and C. =head2 Bare here-doc Using C< << > to initiate a here-doc would create it with an empty terminator, similar to C< <<'' >, so the here-doc would terminate on the next empty line. Omitting the quoted empty string has been deprecated since perl 5, and is a fatal error in perl v5.28.0. =head2 chdir('') Passing an empty string or C to C would change to the home directory, but this usage is deprecated in perl v5.8.0 and throws an error in perl v5.24.0. Instead, call C with no arguments for this behavior. =head2 defined on array/hash Using the function C on an array or hash probably does not do what you expected, and is deprecated in perl v5.6.2 and throws a fatal error in perl v5.22.0. To check if an array or hash is non-empty, test if it has elements. if (@foo) { ... } if (keys %bar) { ... } =head2 do SUBROUTINE(LIST) This form of C to call a subroutine has been deprecated since perl 5, and is removed in perl v5.20.0. =head2 NBSP in \N{...} Use of the "no-break space" character in L is deprecated in perl v5.22.0 and an error in perl v5.26.0. =head2 POSIX character functions Several character matching functions in L.pm are deprecated in perl v5.20.0. See the L documentation for more details. Most uses of these functions can be replaced with appropriate regex matches. isalnum, isalpha, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isspace, issuper, isxdigit =head2 POSIX::tmpnam() The C function from L.pm is deprecated in perl v5.22.0 and removed in perl v5.26.0. Use L instead. =head2 qw(...) as parentheses Literal parentheses are required for certain statements such as a C construct. Using a C list literal without surrounding parentheses in this syntax is deprecated in perl v5.14.0 and a syntax error in perl v5.18.0. Wrap the literal in parentheses: C. =head2 require ::Foo::Bar A bareword C (or C) starting with a double colon would inadvertently translate to a path starting with C. Starting in perl v5.26.0, this is a fatal error. =head2 UNIVERSAL->import() The method C<< UNIVERSAL->import() >> and similarly passing import arguments to C is deprecated in perl v5.12.0 and throws a fatal error in perl v5.22.0. Calling C with no arguments is not an error, but serves no purpose. =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 CAVEATS This policy is incomplete, as many deprecations are difficult to test for statically. It is recommended to use L or L to test your code under newer versions of Perl, with C enabled. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L DiscouragedModules.pm100644001750001750 2300114734076151 30337 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::DiscouragedModules; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy'; our $VERSION = 'v1.0.4'; sub supported_parameters { ( { name => 'allowed_modules', description => 'Modules that you want to allow, despite being discouraged.', behavior => 'string list', }, ) } sub default_severity { $SEVERITY_HIGH } sub default_themes { 'community' } sub applies_to { 'PPI::Statement::Include' } my %modules = ( 'AnyEvent' => 'AnyEvent\'s author refuses to use public bugtracking and actively breaks interoperability. POE, IO::Async, and Mojo::IOLoop are widely used and interoperable async event loops.', 'Any::Moose' => 'Any::Moose is deprecated. Use Moo instead.', 'Class::DBI' => 'Class::DBI is an ancient database ORM abstraction layer which is buggy and abandoned. See DBIx::Class for a more modern DBI-based ORM, or Mad::Mapper for a Mojolicious-style ORM.', 'CGI' => 'CGI.pm is an ancient module for communicating via the CGI protocol, with tons of bad practices and cruft. Use a modern framework such as those based on Plack (Web::Simple, Dancer2, Catalyst) or Mojolicious, they can still be served via CGI if you choose. Use CGI::Tiny if you are limited to the CGI protocol.', 'Coro' => 'Coro abuses Perl internals in an unsupported way. Consider Future and Future::AsyncAwait in combination with event loops for similar semantics.', 'Error' => 'Error.pm is overly magical and discouraged by its maintainers. Try Throwable for exception classes in Moo/Moose, or Exception::Class otherwise. Try::Tiny or Syntax::Keyword::Try are recommended for the try/catch syntax.', 'File::Slurp' => 'File::Slurp gets file encodings all wrong, line endings on win32 are messed up, and it was written before layers were properly added. Use File::Slurper, Path::Tiny, Data::Munge, or Mojo::File.', 'FindBin' => 'FindBin depends on the sometimes vague definition of "initial script" and can\'t be updated to fix bugs in old Perls. Use Path::This or lib::relative to work with the absolute path of the current source file instead.', 'HTML::Template' => 'HTML::Template is an old and buggy module, try Template Toolkit, Mojo::Template, or Text::Xslate instead, or HTML::Template::Pro if you must use the same syntax.', 'IO::Socket::INET6' => 'IO::Socket::INET6 is an old attempt at an IPv6 compatible version of IO::Socket::INET, but has numerous issues and is discouraged by the maintainer in favor of IO::Socket::IP, which transparently creates IPv4 and IPv6 sockets.', 'IP::World' => 'IP::World is deprecated as its databases are in one case discontinued, in the other no longer updated. Therefore its accuracy is ever-decreasing. Try GeoIP2 instead.', 'JSON::Any' => 'JSON::Any is deprecated. Use JSON::MaybeXS instead.', 'JSON::XS' => 'JSON::XS\'s author refuses to use public bugtracking and actively breaks interoperability. Cpanel::JSON::XS is a fork with several bugfixes and a more collaborative maintainer. See also JSON::MaybeXS. Note that JSON (the distribution) uses JSON::XS by default when installed.', 'Net::IRC' => 'Net::IRC is an ancient module implementing the IRC protocol. Use a modern event-loop-based module instead. Choices are POE::Component::IRC (and Bot::BasicBot based on that), Net::Async::IRC, and Mojo::IRC.', 'Switch' => 'Switch.pm is a buggy and outdated source filter which can cause any number of strange errors, in addition to the problems with smart-matching shared by its replacement, the \'switch\' feature (given/when). Try Switch::Plain or Syntax::Keyword::Match instead.', 'XML::Simple' => 'XML::Simple tries to coerce complex XML documents into perl data structures. This leads to overcomplicated structures and unexpected behavior. Use a proper DOM parser instead like XML::LibXML, XML::TreeBuilder, XML::Twig, or Mojo::DOM.', ); sub _violation { my ($self, $module, $elem) = @_; my $desc = "Used module $module"; my $expl = $modules{$module} // "Module $module is discouraged."; return $self->violation($desc, $expl, $elem); } sub violates { my ($self, $elem) = @_; return () unless defined $elem->module and exists $modules{$elem->module} and not exists $self->{_allowed_modules}{$elem->module}; return $self->_violation($elem->module, $elem); } 1; =head1 NAME Perl::Critic::Policy::Community::DiscouragedModules - Various modules discouraged from use =head1 DESCRIPTION Various modules are discouraged by some subsets of the community, for various reasons which may include: buggy behavior, cruft, performance problems, maintainer issues, or simply better modern replacements. This is a high severity complement to L. =head1 MODULES =head2 AnyEvent L's author refuses to use public bugtracking and actively breaks interoperability. L, L, and L are widely used and interoperable async event loops. =head2 Any::Moose L is deprecated. Use L instead. =head2 Class::DBI L is an ancient database L abstraction layer which is buggy and abandoned. See L for a more modern L-based ORM, or L for a L-style ORM. =head2 CGI L.pm is an ancient module for communicating via the CGI protocol, with tons of bad practices and cruft. Use a modern framework such as those based on L (L, L, L) or L, they can still be served via CGI if you choose. Use L if you are limited to the CGI protocol. =head2 Coro L abuses Perl internals in an unsupported way. Consider L and L in combination with event loops for similar semantics. =head2 Error L.pm is overly magical and discouraged by its maintainers. Try L for exception classes in L/L, or L otherwise. L or L are recommended for the C/C syntax. =head2 FindBin L is often used to retrieve the absolute path to the directory containing the initially executed script, a mechanism which is not always logically clear. Additionally, it has serious bugs on old Perls and can't be updated from CPAN to fix them. The L module provides similar variables and constants based on the absolute path to the current source file. The L module resolves passed relative paths to the current source file for the common case of adding local module include directories. Each of these documents examples of achieving the same behavior with core modules. =head2 File::Slurp L gets file encodings all wrong, line endings on win32 are messed up, and it was written before layers were properly added. Use L, L, L, or L. =head2 HTML::Template L is an old and buggy module, try L, L, or L instead, or L if you must use the same syntax. =head2 IO::Socket::INET6 L is an old attempt at an IPv6 compatible version of L, but has numerous issues and is discouraged by the maintainer in favor of L, which transparently creates IPv4 and IPv6 sockets. =head2 IP::World L was built from two free publicly available databases. However, over the years one of them was discontinued, and the other is no longer being updated. Therefore the module's accuracy is ever-decreasing. Try L as an alternative. That code is I deprecated, but at least its database is still updated. =head2 JSON::Any L is deprecated. Use L instead. =head2 JSON::XS L's author refuses to use public bugtracking and actively breaks interoperability. L is a fork with several bugfixes and a more collaborative maintainer. See also L. Note that L (the distribution) uses L by default when installed. =head2 Net::IRC L is an ancient module implementing the IRC protocol. Use a modern event-loop-based module instead. Choices are L (used for L), L, and L. =head2 Switch L.pm is a buggy and outdated source filter which can cause any number of strange errors, in addition to the problems with smart-matching shared by its replacement, L (C/C). Try L or L instead. =head2 XML::Simple L tries to coerce complex XML documents into perl data structures. This leads to overcomplicated structures and unexpected behavior. Use a proper DOM parser instead like L, L, L, or L. =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION Occasionally you may find yourself needing to use one of these discouraged modules, and do not want the warnings. You can do so by putting something like the following in a F<.perlcriticrc> file like this: [Community::DiscouragedModules] allowed_modules = FindBin Any::Moose The same option is offered for L. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L SplitQuotedPattern.pm100644001750001750 675214734076151 30366 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::SplitQuotedPattern; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy'; our $VERSION = 'v1.0.4'; use constant DESC => 'split() called with a quoted pattern'; use constant EXPL => 'The first argument to split() is a regex pattern, not a string (other than the space character special case). Use slashes to quote the pattern argument.'; sub supported_parameters { ( { name => 'allow_unquoted_patterns', description => 'Allow unquoted expressions as the pattern argument to split', default_string => '0', behavior => 'boolean', }, ) } sub default_severity { $SEVERITY_LOWEST } sub default_themes { 'community' } sub applies_to { 'PPI::Token::Word' } sub violates { my ($self, $elem) = @_; return () unless $elem eq 'split' and is_function_call $elem; my @args = parse_arg_list $elem; return () unless @args; my $pattern = $args[0][0]; return $self->violation(DESC, EXPL, $elem) unless $pattern->isa('PPI::Token::Regexp::Match') or $pattern->isa('PPI::Token::QuoteLike::Regexp') or ($pattern->isa('PPI::Token::Quote') and (!length $pattern->string or $pattern->string eq ' ')) or ($self->{_allow_unquoted_patterns} and !$pattern->isa('PPI::Token::Quote')); return (); } 1; =head1 NAME Perl::Critic::Policy::Community::SplitQuotedPattern - Quote the split() pattern argument with regex slashes =head1 DESCRIPTION The first argument to the C function is a regex pattern, not a string. It is commonly passed as a quoted string which does not make this clear, and can lead to bugs when the string unintentionally contains unescaped regex metacharacters. Regardless of the method of quoting, it will be parsed as a pattern (apart from the space character special case described below). Use slashes to quote this argument to make it clear that it is a regex pattern. Note that the special case of passing a single space character must be passed as a quoted string, not a pattern. Additionally, this policy does not warn about passing an empty string as this is a common idiom to split a string into individual characters which does not risk containing regex metacharacters. By default, this policy also prohibits unquoted patterns such as scalar variables, since this does not indicate that the argument is interpreted as a regex pattern and not a string (unless it is a string containing a single space character). split 'foo', $string; # not ok split '.', $string; # not ok split $pat, $string; # not ok split /foo/, $string; # ok split /./, $string; # ok split /$pat/, $string; # ok split qr/./, $string; # ok split ' ', $string; # ok (and distinct from split / /) This policy is similar to the core policy L, but additionally allows empty string split patterns, and disallows unquoted split patterns by default. =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy can be configured to allow passing unquoted patterns (such as scalar variables), by putting an entry in a F<.perlcritic> file like this: [Community::SplitQuotedPattern] allow_unquoted_patterns = 1 =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2024, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L BarewordFilehandles.pm100644001750001750 473614734076151 30457 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::BarewordFilehandles; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy'; our $VERSION = 'v1.0.4'; use constant DESC => 'Using bareword filehandles'; use constant EXPL => 'Bareword filehandles are a legacy feature, creating the filehandles as package variables. Use lexical, scoped filehandles instead (open my $fh, ...).'; sub supported_parameters { () } sub default_severity { $SEVERITY_HIGH } sub default_themes { 'community' } sub applies_to { 'PPI::Token::Word' } my %openers = ( accept => 1, open => 1, opendir => 1, pipe => 2, socket => 1, socketpair => 2, ); my %builtins = ( ARGV => 1, ARGVOUT => 1, DATA => 1, STDERR => 1, STDIN => 1, STDOUT => 1, ); sub violates { my ($self, $elem) = @_; return () unless exists $openers{$elem} and is_function_call $elem; my $num_handles = $openers{$elem}; my @args = parse_arg_list $elem; my @handles = splice @args, 0, $num_handles; my @violations; foreach my $handle (@handles) { my $name = pop @$handle // next; push @violations, $self->violation(DESC, EXPL, $elem) if $name->isa('PPI::Token::Word') and !exists $builtins{$name}; } return @violations; } 1; =head1 NAME Perl::Critic::Policy::Community::BarewordFilehandles - Don't use bareword filehandles other than built-ins =head1 DESCRIPTION Bareword filehandles are allowed in C as a legacy feature, but will use a global package variable. Instead, use a lexical variable with C so that the filehandle is scoped to the current block, and will be automatically closed when it goes out of scope. Built-in bareword filehandles like C and C are ok. open FH, '<', $filename; # not ok open my $fh, '<', $filename; # ok This policy is similar to the core policy L, but allows more combinations of built-in bareword handles and filehandle-opening functions such as C and C. =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L, L PreferredAlternatives.pm100644001750001750 765014734076151 31051 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::PreferredAlternatives; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy'; our $VERSION = 'v1.0.4'; sub supported_parameters { ( { name => 'allowed_modules', description => 'Modules that you want to allow, despite there being a preferred alternative.', behavior => 'string list', }, ) } sub default_severity { $SEVERITY_LOW } sub default_themes { 'community' } sub applies_to { 'PPI::Statement::Include' } my %modules = ( 'Getopt::Std' => 'Getopt::Std was the original very simplistic command-line option processing module. It is now obsoleted by the much more complete solution Getopt::Long, which also supports short options, and is wrapped by module such as Getopt::Long::Descriptive and Getopt::Long::Modern for simpler usage.', 'JSON' => 'JSON.pm is old and full of slow logic. Use JSON::MaybeXS instead, it is a drop-in replacement in most cases.', 'List::MoreUtils' => 'List::MoreUtils is a far more complex distribution than it needs to be. Use List::SomeUtils instead, or see List::Util or List::UtilsBy for alternatives.', 'Mouse' => 'Mouse was created to be a faster version of Moose, a niche that has since been better filled by Moo. Use Moo instead.', 'Readonly' => 'Readonly.pm is buggy and slow. Use Const::Fast or ReadonlyX instead, or the core pragma constant.', ); sub _violation { my ($self, $module, $elem) = @_; my $desc = "Used module $module"; my $expl = $modules{$module} // "Module $module has preferred alternatives."; return $self->violation($desc, $expl, $elem); } sub violates { my ($self, $elem) = @_; return () unless defined $elem->module and exists $modules{$elem->module} and not exists $self->{_allowed_modules}{$elem->module}; return $self->_violation($elem->module, $elem); } 1; =head1 NAME Perl::Critic::Policy::Community::PreferredAlternatives - Various modules with preferred alternatives =head1 DESCRIPTION Various modules have alternatives that are preferred by some subsets of the community, for various reasons which may include: buggy behavior, cruft, performance problems, maintainer issues, or simply better modern replacements. This is a low severity complement to L. =head1 MODULES =head2 Getopt::Std L was the original very simplistic command-line option processing module. It is now obsoleted by the much more complete solution L, which also supports short options, and is wrapped by modules such as L and L for simpler usage. =head2 JSON L.pm is old and full of slow logic. Use L instead, it is a drop-in replacement in most cases. =head2 List::MoreUtils L is a far more complex distribution than it needs to be. Use L instead, or see L or L for alternatives. =head2 Mouse L was created to be a faster version of L, a niche that has since been better filled by L. Use L instead. =head2 Readonly L.pm is buggy and slow. Use L or L instead, or the core pragma L. =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION Occasionally you may find yourself needing to use one of these non-preferred modules, and do not want the warnings. You can do so by putting something like the following in a F<.perlcriticrc> file like this: [Community::PreferredAlternatives] allowed_modules = Getopt::Std JSON The same option is offered for L. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L IndirectObjectNotation.pm100644001750001750 447214734076151 31154 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::IndirectObjectNotation; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy::Objects::ProhibitIndirectSyntax'; our $VERSION = 'v1.0.4'; sub default_severity { $SEVERITY_HIGHEST } sub default_themes { 'community' } 1; =head1 NAME Perl::Critic::Policy::Community::IndirectObjectNotation - Don't call methods indirectly =head1 DESCRIPTION Perl allows a form of method call where the method name is first, followed by the invocant (class or object to call the method on), then the argument list. This is an unfortunate legacy syntax that should no longer be used. See L and L for more information. my $obj = new My::Class @args; # not ok my $obj = My::Class->new(@args); # ok It is difficult to detect indirect object notation by static analysis, so this policy only forbids the C method call by default, as it is highly unlikely to be the name of a standard subroutine call. Consider using the L pragma to cause the code to warn or die when indirect object notation is used. On Perl 5.32 or newer (or automatically with C or newer), L can be disabled to prevent the parser from interpreting syntax as indirect object notation. This policy is a subclass of the L core policy L, and performs the same function but in the C theme. =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy can be configured, in the same way as its parent policy L, to attempt to forbid additional method names from being called indirectly. Be aware this may lead to false positives as it is difficult to detect indirect object notation by static analysis. The C subroutine is always forbidden in addition to these. [Community::IndirectObjectNotation] forbid = create destroy =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L, L LexicalForeachIterator.pm100644001750001750 277514734076151 31137 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::LexicalForeachIterator; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy::Variables::RequireLexicalLoopIterators'; our $VERSION = 'v1.0.4'; sub default_severity { $SEVERITY_HIGH } sub default_themes { 'community' } 1; =head1 NAME Perl::Critic::Policy::Community::LexicalForeachIterator - Don't use undeclared foreach loop iterators =head1 DESCRIPTION It's possible to use a variable that's already been declared as the iterator for a L, but this will localize the variable to the loop and its value will be reverted after the loop is done. Always declare the loop iterator in the lexical scope of the loop with C. foreach $foo (...) {...} # not ok for $bar (...) {...} # not ok foreach my $foo (...) {...} # ok for my $bar (...) {...} # ok This policy is a subclass of the L core policy L, and performs the same function but in the C theme. =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L PackageMatchesFilename.pm100644001750001750 522714734076151 31050 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::PackageMatchesFilename; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use Path::Tiny 'path'; use parent 'Perl::Critic::Policy'; our $VERSION = 'v1.0.4'; use constant DESC => 'No package matching the module filename'; use constant EXPL => 'A Perl module file is expected to contain a matching package name, so it can be used after loading it from the filesystem. A module file that doesn\'t contain a matching package name usually indicates an error.'; sub default_severity { $SEVERITY_HIGH } sub default_themes { 'community' } sub applies_to { 'PPI::Document' } sub violates { my ($self, $elem, $doc) = @_; return () unless $doc->is_module and $doc->filename and $doc->filename =~ m/\.pm\z/; my $packages = $elem->find('PPI::Statement::Package') || []; my $filepath = path($doc->filename)->realpath; my $basename = $filepath->basename(qr/\.pm/); $filepath = $filepath->parent->child($basename); my $found_match; PKG: foreach my $package (@$packages) { my $namespace = $package->namespace; my $path_copy = $filepath; foreach my $part (reverse split /::/, $namespace) { next PKG unless $part eq $path_copy->basename; $path_copy = $path_copy->parent; } $found_match = 1; last; } return () if $found_match; return $self->violation(DESC, EXPL, $elem); } 1; =head1 NAME Perl::Critic::Policy::Community::PackageMatchesFilename - Module files should declare a package matching the filename =head1 DESCRIPTION Perl modules are normally loaded by C (possibly via C or C). When given a module name, C will translate this into a filename and then load whatever that file contains. The file doesn't need to actually contain a package matching the module name initially given to C, but this can be confusing if later operations (including C as called by C) expect the package to exist. Furthermore, the absence of such a package is usually an indicator of a typo in the package name. ## in file My/Module.pm package My::Module; This policy is similar to the core policy L, but only requires that one package name within a module file matches the filename. =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L ConditionalDeclarations.pm100644001750001750 316614734076151 31343 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::ConditionalDeclarations; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy::Variables::ProhibitConditionalDeclarations'; our $VERSION = 'v1.0.4'; sub default_severity { $SEVERITY_HIGH } sub default_themes { 'community' } 1; =head1 NAME Perl::Critic::Policy::Community::ConditionalDeclarations - Don't declare variables conditionally =head1 DESCRIPTION It is possible to add a postfix condition to a variable declaration, like C. However, it is unclear (and undefined) if the variable will be declared when the condition is not met. Instead, declare the variable and then assign to it conditionally, or use the L to assign a value conditionally. my $foo = $bar if $baz; # not ok my ($foo, $bar) = @_ unless $baz; # not ok our $bar = $_ for 0..10; # not ok my $foo; $foo = $bar if $baz; # ok my $foo = $baz ? $bar : undef; # ok This policy is a subclass of the core policy L, and performs the same function but in the C theme. =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L ConditionalImplicitReturn.pm100644001750001750 625414734076151 31706 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::ConditionalImplicitReturn; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy'; use List::Util 'any'; use Perl::Critic::Community::Utils qw(is_empty_return is_structural_block); our $VERSION = 'v1.0.4'; use constant DESC => 'Subroutine may implicitly return a conditional statement'; use constant EXPL => 'When the last statement in a subroutine is a conditional, the return value may unexpectedly be the evaluated condition.'; sub supported_parameters { () } sub default_severity { $SEVERITY_MEDIUM } sub default_themes { 'community' } sub applies_to { 'PPI::Statement::Sub' } my %conditionals = map { ($_ => 1) } qw(if unless); sub violates { my ($self, $elem) = @_; my $block = $elem->block || return (); my $returns = $block->find(sub { my ($elem, $child) = @_; # Don't search in blocks unless we know they are structural if ($child->isa('PPI::Structure::Block')) { return undef unless is_structural_block($child); } return 1 if $child->isa('PPI::Token::Word') and $child eq 'return'; return 0; }); # Check the last statement if any non-empty return is present if ($returns and any { !is_empty_return($_) } @$returns) { my $last = $block->schild(-1); # Check if last statement is a conditional if ($last and $last->isa('PPI::Statement::Compound') and $last->schildren and exists $conditionals{$last->schild(0)}) { # Make sure there isn't an "else" unless (any { $_->isa('PPI::Token::Word') and $_ eq 'else' } $last->schildren) { return $self->violation(DESC, EXPL, $last); } } } return (); } 1; =head1 NAME Perl::Critic::Policy::Community::ConditionalImplicitReturn - Don't end a subroutine with a conditional block =head1 DESCRIPTION If the last statement in a subroutine is a conditional block such as C, and the C condition is not handled, the subroutine will return an unexpected value when the condition fails, and it is most likely a logic error. Specify a return value after the conditional, or handle the C condition. sub { ... if ($foo) { return 1 } } # not ok sub { ... if ($foo) { return 1 } return 0 } # ok sub { ... if ($foo) { return 1 } else { return 0 } } # ok This policy only applies if the subroutine contains a return statement with an explicit return value, indicating it is not intended to be used in void context. =head1 CAVEATS This policy currently only checks for implicitly returned conditionals in named subroutines, anonymous subroutines are not checked. Also, return statements within blocks, other than compound statements like C and C, are not considered when determining if a function is intended to be used in void context. =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L WhileDiamondDefaultAssignment.pm100644001750001750 725614734076151 32455 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::WhileDiamondDefaultAssignment; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy'; our $VERSION = 'v1.0.4'; use constant DESC => '<>/<<>>/readline/readdir/each result not explicitly assigned in while condition'; use constant EXPL => 'When used alone in a while condition, the <>/<<>> operator, readline, readdir, and each functions assign their result to $_, but do not localize it. Assign the result to an explicit lexical variable instead (my $line = <...>, my $dir = readdir ...)'; sub supported_parameters { () } sub default_severity { $SEVERITY_HIGH } sub default_themes { 'community' } sub applies_to { 'PPI::Token::Word' } my %bad_functions = ( each => 1, readdir => 1, readline => 1, ); sub violates { my ($self, $elem) = @_; return () unless $elem eq 'while' or $elem eq 'for'; my $next = $elem->snext_sibling || return (); # Detect for (;<>;) if ($elem eq 'for') { return () unless $next->isa('PPI::Structure::For'); my @statements = grep { $_->isa('PPI::Statement') } $next->children; return () unless @statements >= 2; my $middle = $statements[1]; return $self->violation(DESC, EXPL, $elem) if $middle->schildren and $middle->schild(0)->isa('PPI::Token::QuoteLike::Readline'); } elsif ($elem eq 'while') { # while (<>) {} or ... while <> if ($next->isa('PPI::Structure::Condition')) { $next = $next->schild(0); return () unless defined $next and $next->isa('PPI::Statement'); $next = $next->schild(0); return () unless defined $next; } return $self->violation(DESC, EXPL, $elem) if $next->isa('PPI::Token::QuoteLike::Readline'); if ($next->isa('PPI::Token::Word') and exists $bad_functions{$next} and is_function_call $next) { return $self->violation(DESC, EXPL, $elem); } } return (); } 1; =head1 NAME Perl::Critic::Policy::Community::WhileDiamondDefaultAssignment - Don't use while with implicit assignment to $_ =head1 DESCRIPTION The diamond operator CE> (or CEEE>), and functions C, C, and C are extra magical in a while condition: if it is the only thing in the condition, it will assign its result to C<$_>, but it does not localize C<$_> to the while loop. (Note, this also applies to a CE;)> construct.) This can unintentionally confuse outer loops that are already using C<$_> to iterate. In addition, using C<$_> at all means that your loop can get confused by other code which does not politely localize its usage of the global variable. To avoid these possibilities, assign the result of the diamond operator or these functions to an explicit lexical variable. while (<$fh>) { ... } # not ok while (<<>>) { ... } # not ok ... while ; # not ok for (;<>;) { ... } # not ok while (readline $fh) { ... } # not ok while (readdir $dh) { ... } # not ok while (my $line = <$fh>) { ... } # ok while (my $line = <<>>) { ... } # ok ... while $line = ; # ok for (;my $line = <>;) { ... } # ok while (my $line = readline $fh) { ... } # ok while (my $dir = readdir $dh) { ... } # ok =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L MultidimensionalArrayEmulation.pm100644001750001750 710014734076151 32731 0ustar00grinnzgrinnz000000000000Perl-Critic-Community-v1.0.4/lib/Perl/Critic/Policy/Communitypackage Perl::Critic::Policy::Community::MultidimensionalArrayEmulation; use strict; use warnings; use Perl::Critic::Utils qw(:severities :classification :ppi); use parent 'Perl::Critic::Policy'; use List::Util 'any'; our $VERSION = 'v1.0.4'; use constant DESC => 'Use of multidimensional array emulation in hash subscript'; use constant EXPL => 'A list in a hash subscript used with the $ sigil triggers Perl 4 multidimensional array emulation. Nest structures using references instead.'; sub supported_parameters { () } sub default_severity { $SEVERITY_LOW } sub default_themes { 'community' } sub applies_to { 'PPI::Structure::Subscript' } sub violates { my ($self, $elem) = @_; return () unless $elem->complete and $elem->braces eq '{}'; my @contents = $elem->schildren; @contents = $contents[0]->schildren if @contents == 1 and $contents[0]->isa('PPI::Statement::Expression'); # check for function call with no parentheses; following args won't trigger MAE if (@contents > 1 and $contents[0]->isa('PPI::Token::Word') and !$contents[1]->isa('PPI::Structure::List') and !($contents[1]->isa('PPI::Token::Operator') and ($contents[1] eq ',' or $contents[1] eq '=>'))) { return (); } # check if contains top level , or multi-word qw return () unless any { ($_->isa('PPI::Token::Operator') and ($_ eq ',' or $_ eq '=>')) or ($_->isa('PPI::Token::QuoteLike::Words') and (my @words = $_->literal) > 1) } @contents; # check if it's a postderef slice my $prev = $elem->sprevious_sibling; return () if $prev and $prev->isa('PPI::Token::Cast') and ($prev eq '@' or $prev eq '%'); # check if it's a slice my ($cast, $found_symbol); $prev = $elem; while ($prev = $prev->sprevious_sibling) { last if $found_symbol and !$prev->isa('PPI::Token::Cast'); if ($prev->isa('PPI::Token::Symbol')) { $cast = $prev->raw_type; $found_symbol = 1; } elsif ($prev->isa('PPI::Structure::Block')) { $found_symbol = 1; } elsif ($found_symbol and $prev->isa('PPI::Token::Cast')) { $cast = $prev; } else { last unless $prev->isa('PPI::Structure::Subscript') or ($prev->isa('PPI::Token::Operator') and $prev eq '->'); } } return () if $cast and ($cast eq '@' or $cast eq '%'); return $self->violation(DESC, EXPL, $elem); } 1; =head1 NAME Perl::Critic::Policy::Community::MultidimensionalArrayEmulation - Don't use multidimensional array emulation =head1 DESCRIPTION When used with the C<@> or C<%> sigils, a list in a hash subscript (C<{}>) will access multiple elements of the hash as a slice. With the C<$> sigil however, it accesses the single element at the key defined by joining the list with the subscript separator C<$;>. This feature is known as L and provided a way to emulate a multidimensional structure before Perl 5 introduced references. Perl now supports true multidimensional structures, so this feature is now unnecessary in most cases. In Perl 5.34 or newer, or automatically under C or newer, L can be disabled to remove this syntax from the parser. $foo{$x,$y,$z} # not ok $foo{qw(a b c)} # not ok $foo{$x}{$y}{$z} # ok @foo{$x,$y,$z} # ok =head1 AFFILIATION This policy is part of L. =head1 CONFIGURATION This policy is not configurable except for the standard options. =head1 AUTHOR Dan Book, C =head1 COPYRIGHT AND LICENSE Copyright 2015, Dan Book. This library is free software; you may redistribute it and/or modify it under the terms of the Artistic License version 2.0. =head1 SEE ALSO L