File Coverage

blib/lib/Perl/Critic/Policy/Community/SplitQuotedPattern.pm
Criterion Covered Total %
statement 28 29 96.5
branch 5 6 83.3
condition 18 21 85.7
subroutine 10 11 90.9
pod 4 5 80.0
total 65 72 90.2


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::Community::SplitQuotedPattern;
2              
3 1     1   459840 use strict;
  1         2  
  1         45  
4 1     1   7 use warnings;
  1         2  
  1         70  
5              
6 1     1   7 use Perl::Critic::Utils qw(:severities :classification :ppi);
  1         3  
  1         115  
7 1     1   615 use parent 'Perl::Critic::Policy';
  1         2  
  1         9  
8              
9             our $VERSION = 'v1.0.4';
10              
11 1     1   23768 use constant DESC => 'split() called with a quoted pattern';
  1         3  
  1         133  
12 1     1   8 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.';
  1         2  
  1         349  
13              
14             sub supported_parameters {
15             (
16             {
17 6     6 0 34457 name => 'allow_unquoted_patterns',
18             description => 'Allow unquoted expressions as the pattern argument to split',
19             default_string => '0',
20             behavior => 'boolean',
21             },
22             )
23             }
24 8     8 1 243 sub default_severity { $SEVERITY_LOWEST }
25 0     0 1 0 sub default_themes { 'community' }
26 6     6 1 106810 sub applies_to { 'PPI::Token::Word' }
27              
28             sub violates {
29 31     31 1 2135 my ($self, $elem) = @_;
30 31 100 66     147 return () unless $elem eq 'split' and is_function_call $elem;
31            
32 29         13898 my @args = parse_arg_list $elem;
33 29 50       7656 return () unless @args;
34            
35 29         79 my $pattern = $args[0][0];
36             return $self->violation(DESC, EXPL, $elem)
37             unless $pattern->isa('PPI::Token::Regexp::Match')
38             or $pattern->isa('PPI::Token::QuoteLike::Regexp')
39             or ($pattern->isa('PPI::Token::Quote') and (!length $pattern->string or $pattern->string eq ' '))
40 29 100 100     407 or ($self->{_allow_unquoted_patterns} and !$pattern->isa('PPI::Token::Quote'));
      100        
      100        
      100        
      66        
      66        
41            
42 21         268 return ();
43             }
44              
45             1;
46              
47             =head1 NAME
48              
49             Perl::Critic::Policy::Community::SplitQuotedPattern - Quote the split() pattern
50             argument with regex slashes
51              
52             =head1 DESCRIPTION
53              
54             The first argument to the C<split()> function is a regex pattern, not a string.
55             It is commonly passed as a quoted string which does not make this clear, and
56             can lead to bugs when the string unintentionally contains unescaped regex
57             metacharacters. Regardless of the method of quoting, it will be parsed as a
58             pattern (apart from the space character special case described below). Use
59             slashes to quote this argument to make it clear that it is a regex pattern.
60              
61             Note that the special case of passing a single space character must be passed
62             as a quoted string, not a pattern. Additionally, this policy does not warn
63             about passing an empty string as this is a common idiom to split a string into
64             individual characters which does not risk containing regex metacharacters.
65              
66             By default, this policy also prohibits unquoted patterns such as scalar
67             variables, since this does not indicate that the argument is interpreted as a
68             regex pattern and not a string (unless it is a string containing a single space
69             character).
70              
71             split 'foo', $string; # not ok
72             split '.', $string; # not ok
73             split $pat, $string; # not ok
74             split /foo/, $string; # ok
75             split /./, $string; # ok
76             split /$pat/, $string; # ok
77             split qr/./, $string; # ok
78             split ' ', $string; # ok (and distinct from split / /)
79              
80             This policy is similar to the core policy
81             L<Perl::Critic::Policy::BuiltinFunctions::ProhibitStringySplit>, but
82             additionally allows empty string split patterns, and disallows unquoted split
83             patterns by default.
84              
85             =head1 AFFILIATION
86              
87             This policy is part of L<Perl::Critic::Community>.
88              
89             =head1 CONFIGURATION
90              
91             This policy can be configured to allow passing unquoted patterns (such as
92             scalar variables), by putting an entry in a F<.perlcritic> file like this:
93              
94             [Community::SplitQuotedPattern]
95             allow_unquoted_patterns = 1
96              
97             =head1 AUTHOR
98              
99             Dan Book, C<dbook@cpan.org>
100              
101             =head1 COPYRIGHT AND LICENSE
102              
103             Copyright 2024, Dan Book.
104              
105             This library is free software; you may redistribute it and/or modify it under
106             the terms of the Artistic License version 2.0.
107              
108             =head1 SEE ALSO
109              
110             L<Perl::Critic>