Perl::Critic::Policy::RegularExpressions::ProhibitEmptyAlternatives - Beware empty alternatives, because they always match.
This Policy is stand-alone, and is not part of the core Perl::Critic.
This Perl::Critic policy checks for empty alternatives; that is, things like /a||b/. The problem with these is that they always match, which is very probably not what you want.
/a||b/
The possible exception is the final alternative, where you may indeed want something like /glass(?es|y|)/ to match 'glass', 'glassy', or 'glasses', though this is not the usual idiom. This policy does not allow empty final alternatives by default, but it can be configured to do so.
/glass(?es|y|)/
'glass'
'glassy'
'glasses'
Note that empty alternatives are syntax errors in extended bracketed character classes, so this policy treats them as violations no matter how it is configured.
This policy was inspired by y's https://github.com/Perl-Critic/Perl-Critic/issues/727.
This policy supports the following configuration items.
By default, this policy prohibits all empty alternatives, since they match anything. It may make sense, though, to leave the final alternative in a regexp or group empty. For example, /(?:Larry|Moe|Curly|)/ is equivalent to the perhaps-more-usual idiom /(?:Larry|Moe|Curly)?/.
/(?:Larry|Moe|Curly|)/
/(?:Larry|Moe|Curly)?/
If you wish to allow this, you can add a block like this to your .perlcriticrc file:
[RegularExpressions::ProhibitEmptyAlternatives] allow_empty_final_alternative = 1
It may make sense to allow empty alternatives if they occur in a group that is anchored on the right. For example,
"What ho, Porthos!" =~ /(|Athos|Porthos|Aramis)!/
captures 'Porthos' because the regular expression engine sees 'Porthos!' before it sees '!'.
'Porthos'
'Porthos!'
'!'
[RegularExpressions::ProhibitEmptyAlternatives] allow_if_group_anchored = 1
Caveat: I believe that a full static analysis of this case is not possible when back references or recursions must be considered as anchors. Correct analysis of groups (captures or otherwise) is not currently attempted. In these cases the code assumes that the entity represents an anchor.
It may make sense to ignore some files. For example, Module::Install component inc/Module/Install/Metadata.pm is known to violate this policy, at least in its default configuration -- though it passes if allow_empty_final_alternative is enabled.
allow_empty_final_alternative
If you wish to ignore certain files, you can add a block like this to your .perlcriticrc file:
[RegularExpressions::ProhibitEmptyAlternatives] allow_if_group_anchored = inc/Module/Install/Metadata\.pm\z
The value is a regular expression.
Thomas R. Wyant, III wyant at cpan dot org
Copyright (C) 2020 Thomas R. Wyant, III
This program is free software; you can redistribute it and/or modify it under the same terms as Perl 5.10.0. For more details, see the full text of the licenses in the directory LICENSES.
This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose.
To install Perl::Critic::Policy::RegularExpressions::ProhibitEmptyAlternatives, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Perl::Critic::Policy::RegularExpressions::ProhibitEmptyAlternatives
CPAN shell
perl -MCPAN -e shell install Perl::Critic::Policy::RegularExpressions::ProhibitEmptyAlternatives
For more information on module installation, please visit the detailed CPAN module installation guide.