| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
use strict; |
|
3
|
1
|
|
|
1
|
|
426
|
use warnings; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
22
|
|
|
4
|
1
|
|
|
1
|
|
5
|
|
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
21
|
|
|
5
|
|
|
|
|
|
|
use List::Util 'any', 'none'; |
|
6
|
1
|
|
|
1
|
|
5
|
use Perl::Critic::Utils qw(:severities :classification :ppi); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
62
|
|
|
7
|
1
|
|
|
1
|
|
5
|
use parent 'Perl::Critic::Policy'; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
50
|
|
|
8
|
1
|
|
|
1
|
|
314
|
|
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
6
|
|
|
9
|
|
|
|
|
|
|
our $VERSION = 'v1.0.3'; |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
4
|
|
|
4
|
0
|
31219
|
my %features = ( |
|
13
|
75
|
|
|
75
|
1
|
603
|
':=' => 'Use of := as an empty attribute list is deprecated in perl v5.12.0, use = alone.', |
|
14
|
0
|
|
|
0
|
1
|
0
|
'$[' => 'Use of $[ is deprecated in perl v5.12.0. See Array::Base and String::Base.', |
|
15
|
4
|
|
|
4
|
1
|
171828
|
'/\\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.', |
|
16
|
|
|
|
|
|
|
'?PATTERN?' => 'Use of ? as a match regex delimiter without an initial m is deprecated in perl v5.14.0. Use m?PATTERN? instead.', |
|
17
|
|
|
|
|
|
|
'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.', |
|
18
|
|
|
|
|
|
|
'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 <<\'\'.', |
|
19
|
|
|
|
|
|
|
'chdir(\'\')' => 'Use of chdir(\'\') or chdir(undef) to chdir home is deprecated in perl v5.8.0. Use chdir() instead.', |
|
20
|
|
|
|
|
|
|
'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) { ... }', |
|
21
|
|
|
|
|
|
|
'do SUBROUTINE(LIST)' => 'Use of do to call a subroutine is deprecated in perl 5.', |
|
22
|
|
|
|
|
|
|
'NBSP in \\N{...}' => 'Use of the "no-break space" character in character names is deprecated in perl v5.22.0.', |
|
23
|
|
|
|
|
|
|
'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.', |
|
24
|
|
|
|
|
|
|
'POSIX::tmpnam()' => 'The tmpnam() function from POSIX is deprecated in perl v5.22.0. Use File::Temp instead.', |
|
25
|
|
|
|
|
|
|
'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.', |
|
26
|
|
|
|
|
|
|
'require ::Foo::Bar' => 'Bareword require starting with a double colon is an error in perl v5.26.0.', |
|
27
|
|
|
|
|
|
|
'UNIVERSAL->import()' => 'The method UNIVERSAL->import() (or passing import arguments to "use UNIVERSAL") is deprecated in perl v5.12.0.', |
|
28
|
|
|
|
|
|
|
); |
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
my %posix_deprecated = map { ($_ => 1, "POSIX::$_" => 1) } |
|
31
|
|
|
|
|
|
|
qw(isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit); |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
my %autoderef_functions = map { ($_ => 1) } |
|
34
|
|
|
|
|
|
|
qw(each keys pop push shift splice unshift values); |
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
my ($self, $feature, $elem) = @_; |
|
37
|
|
|
|
|
|
|
my $desc = "$feature is deprecated"; |
|
38
|
|
|
|
|
|
|
my $expl = $features{$feature} // "$feature is deprecated or removed from recent versions of Perl."; |
|
39
|
|
|
|
|
|
|
return $self->violation($desc, $expl, $elem); |
|
40
|
|
|
|
|
|
|
} |
|
41
|
|
|
|
|
|
|
|
|
42
|
75
|
|
|
75
|
|
316
|
my ($self, $elem) = @_; |
|
43
|
75
|
|
|
|
|
184
|
my $next; |
|
44
|
75
|
|
33
|
|
|
177
|
my $prev; |
|
45
|
75
|
|
|
|
|
214
|
my $parent; |
|
46
|
|
|
|
|
|
|
my @args; |
|
47
|
|
|
|
|
|
|
my @violations; |
|
48
|
|
|
|
|
|
|
if ($elem->isa('PPI::Statement')) { |
|
49
|
1161
|
|
|
1161
|
1
|
5087
|
if ($elem->isa('PPI::Statement::Include')) { |
|
50
|
1161
|
|
|
|
|
3413
|
# use UNIVERSAL ...; |
|
51
|
|
|
|
|
|
|
if ($elem->type eq 'use' and defined $elem->module and $elem->module eq 'UNIVERSAL') { |
|
52
|
1161
|
|
|
|
|
0
|
my @args = $elem->arguments; |
|
53
|
1161
|
|
|
|
|
0
|
if (!@args or !$args[0]->isa('PPI::Structure::List') or $args[0]->schildren) { |
|
54
|
1161
|
|
|
|
|
0
|
push @violations, $self->_violation('UNIVERSAL->import()', $elem); |
|
55
|
1161
|
100
|
|
|
|
3472
|
} |
|
|
|
100
|
|
|
|
|
|
|
56
|
199
|
100
|
|
|
|
480
|
} |
|
57
|
|
|
|
|
|
|
# require ::Foo::Bar |
|
58
|
13
|
100
|
66
|
|
|
42
|
if (defined $elem->module and $elem->module =~ m/^::/) { |
|
|
|
|
100
|
|
|
|
|
|
59
|
3
|
|
|
|
|
181
|
push @violations, $self->_violation('require ::Foo::Bar', $elem); |
|
60
|
3
|
100
|
100
|
|
|
115
|
} |
|
|
|
|
66
|
|
|
|
|
|
61
|
2
|
|
|
|
|
6
|
} |
|
62
|
|
|
|
|
|
|
} elsif ($elem->isa('PPI::Token')) { |
|
63
|
|
|
|
|
|
|
if ($elem->isa('PPI::Token::Symbol')) { |
|
64
|
|
|
|
|
|
|
# $[ |
|
65
|
13
|
100
|
66
|
|
|
751
|
if ($elem eq '$[') { |
|
66
|
3
|
|
|
|
|
114
|
push @violations, $self->_violation('$[', $elem); |
|
67
|
|
|
|
|
|
|
} |
|
68
|
|
|
|
|
|
|
} elsif ($elem->isa('PPI::Token::Operator')) { |
|
69
|
|
|
|
|
|
|
# := |
|
70
|
903
|
100
|
|
|
|
5480
|
if ($elem eq ':' and $next = $elem->next_sibling and $next->isa('PPI::Token::Operator') and $next eq '=') { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
push @violations, $self->_violation(':=', $elem); |
|
72
|
92
|
100
|
|
|
|
228
|
# ?PATTERN? - PPI parses this as multiple ? operators |
|
73
|
1
|
|
|
|
|
115
|
} elsif ($elem eq '?' and $parent = $elem->parent and $parent->isa('PPI::Statement')) { |
|
74
|
|
|
|
|
|
|
$next = $elem->snext_sibling; |
|
75
|
|
|
|
|
|
|
until (!$next or ($next->isa('PPI::Token::Operator') and $next eq '?')) { |
|
76
|
|
|
|
|
|
|
$next = $next->snext_sibling; |
|
77
|
47
|
100
|
66
|
|
|
83
|
} |
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
78
|
1
|
|
|
|
|
50
|
# If the statement has a : operator, this is probably a ternary operator. |
|
79
|
|
|
|
|
|
|
# PPI also tends to detect the : as a loop label. |
|
80
|
|
|
|
|
|
|
if ($next and none { ($_->isa('PPI::Token::Operator') and $_ eq ':') or $_->isa('PPI::Token::Label') } $parent->schildren) { |
|
81
|
6
|
|
|
|
|
158
|
push @violations, $self->_violation('?PATTERN?', $elem); |
|
82
|
6
|
|
100
|
|
|
140
|
} |
|
|
|
|
100
|
|
|
|
|
|
83
|
14
|
|
|
|
|
242
|
# Bare here-doc - differentiate this from the legitimate << operator |
|
84
|
|
|
|
|
|
|
} elsif ($elem eq '<<' and (!($next = $elem->snext_sibling) |
|
85
|
|
|
|
|
|
|
or ($next->isa('PPI::Token::Operator') and $next ne '~' and $next ne '!' and $next ne '+' and $next ne '-') |
|
86
|
|
|
|
|
|
|
or ($next->isa('PPI::Token::Structure') and $next ne '(' and $next ne '{' and $next ne '['))) { |
|
87
|
6
|
100
|
100
|
17
|
|
201
|
push @violations, $self->_violation('Bare here-doc', $elem); |
|
|
17
|
100
|
100
|
|
|
189
|
|
|
88
|
1
|
|
|
|
|
3
|
} |
|
89
|
|
|
|
|
|
|
} elsif ($elem->isa('PPI::Token::Word')) { |
|
90
|
|
|
|
|
|
|
# UNIVERSAL->import() |
|
91
|
|
|
|
|
|
|
if ($elem eq 'UNIVERSAL' |
|
92
|
|
|
|
|
|
|
and $next = $elem->snext_sibling and $next->isa('PPI::Token::Operator') and $next eq '->' |
|
93
|
|
|
|
|
|
|
and $next = $next->snext_sibling and $next->isa('PPI::Token::Word') and $next eq 'import') { |
|
94
|
4
|
|
|
|
|
301
|
push @violations, $self->_violation('UNIVERSAL->import()', $next); |
|
95
|
|
|
|
|
|
|
# for $x qw(...) |
|
96
|
|
|
|
|
|
|
} elsif (($elem eq 'for' or $elem eq 'foreach') and !$elem->sprevious_sibling) { |
|
97
|
|
|
|
|
|
|
$next = $elem->snext_sibling; |
|
98
|
152
|
100
|
66
|
|
|
283
|
until (!$next or $next->isa('PPI::Structure::List') |
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
99
|
|
|
|
|
|
|
or $next->isa('PPI::Token::QuoteLike::Words')) { |
|
100
|
|
|
|
|
|
|
$next = $next->snext_sibling; |
|
101
|
1
|
|
|
|
|
83
|
} |
|
102
|
|
|
|
|
|
|
if ($next and $next->isa('PPI::Token::QuoteLike::Words')) { |
|
103
|
|
|
|
|
|
|
push @violations, $self->_violation('qw(...) as parentheses', $next); |
|
104
|
2
|
|
|
|
|
71
|
} |
|
105
|
2
|
|
66
|
|
|
71
|
# do SUBROUTINE(LIST) |
|
|
|
|
100
|
|
|
|
|
|
106
|
|
|
|
|
|
|
} elsif ($elem eq 'do' and $next = $elem->snext_sibling) { |
|
107
|
4
|
|
|
|
|
57
|
if ((($next->isa('PPI::Token::Word') and is_function_call $next) |
|
108
|
|
|
|
|
|
|
or ($next->isa('PPI::Token::Symbol') and ($next->raw_type eq '&' or $next->raw_type eq '$'))) |
|
109
|
2
|
100
|
66
|
|
|
61
|
and ($next = $next->snext_sibling and $next->isa('PPI::Structure::List'))) { |
|
110
|
1
|
|
|
|
|
4
|
push @violations, $self->_violation('do SUBROUTINE(LIST)', $elem); |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
# avoid false positives for method calls |
|
113
|
|
|
|
|
|
|
} elsif (!($prev = $elem->sprevious_sibling) or !$prev->isa('PPI::Token::Operator') or $prev ne '->') { |
|
114
|
6
|
100
|
66
|
|
|
377
|
# POSIX character function or POSIX::tmpnam() |
|
|
|
|
66
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
115
|
|
|
|
|
|
|
if (exists $posix_deprecated{$elem} or $elem eq 'tmpnam' or $elem eq 'POSIX::tmpnam') { |
|
116
|
|
|
|
|
|
|
my $is_posix = $elem =~ m/^POSIX::/ ? 1 : 0; |
|
117
|
3
|
|
|
|
|
346
|
(my $function_name = $elem) =~ s/^POSIX:://; |
|
118
|
|
|
|
|
|
|
unless ($is_posix) { |
|
119
|
|
|
|
|
|
|
my $includes = $elem->document->find('PPI::Statement::Include') || []; |
|
120
|
|
|
|
|
|
|
foreach my $stmt (grep { ($_->module // '') eq 'POSIX' } @$includes) { |
|
121
|
|
|
|
|
|
|
my @args = $stmt->arguments; |
|
122
|
139
|
100
|
100
|
|
|
7886
|
$is_posix = 1 if !@args or any { $_ =~ m/\b\Q$function_name\E\b/ } @args; |
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
123
|
48
|
100
|
|
|
|
290
|
} |
|
124
|
48
|
|
|
|
|
245
|
} |
|
125
|
48
|
100
|
|
|
|
213
|
if ($is_posix) { |
|
126
|
36
|
|
50
|
|
|
91
|
push @violations, $self->_violation('POSIX::tmpnam()', $elem) if $function_name eq 'tmpnam'; |
|
127
|
36
|
|
50
|
|
|
175843
|
push @violations, $self->_violation('POSIX character function', $elem) if exists $posix_deprecated{$elem}; |
|
|
96
|
|
|
|
|
1282
|
|
|
128
|
36
|
|
|
|
|
879
|
} |
|
129
|
36
|
100
|
100
|
24
|
|
1107
|
# defined array/hash |
|
|
24
|
|
|
|
|
63
|
|
|
130
|
|
|
|
|
|
|
} elsif ($elem eq 'defined' and $next = $elem->snext_sibling) { |
|
131
|
|
|
|
|
|
|
$next = $next->schild(0) if $next->isa('PPI::Structure::List'); |
|
132
|
48
|
100
|
|
|
|
707
|
if ($next and $next->isa('PPI::Token::Symbol') |
|
133
|
36
|
100
|
|
|
|
92
|
and ($next->raw_type eq '@' or $next->raw_type eq '%') |
|
134
|
36
|
100
|
|
|
|
754
|
and $next->raw_type eq $next->symbol_type) { |
|
135
|
|
|
|
|
|
|
push @violations, $self->_violation('defined on array/hash', $elem); |
|
136
|
|
|
|
|
|
|
} |
|
137
|
|
|
|
|
|
|
# autoderef |
|
138
|
8
|
100
|
|
|
|
380
|
} elsif (exists $autoderef_functions{$elem} and $next = $elem->snext_sibling) { |
|
139
|
8
|
100
|
66
|
|
|
76
|
$next = $next->schild(0) if $next->isa('PPI::Structure::List'); |
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
140
|
|
|
|
|
|
|
$next = $next->schild(0) if $next and $next->isa('PPI::Statement::Expression'); |
|
141
|
|
|
|
|
|
|
if ($next and $next->isa('PPI::Token::Symbol') and $next->raw_type eq '$') { |
|
142
|
2
|
|
|
|
|
114
|
my $is_postderef; |
|
143
|
|
|
|
|
|
|
until (!$next or ($next->isa('PPI::Token::Structure') and $next eq ';') |
|
144
|
|
|
|
|
|
|
or ($next->isa('PPI::Token::Operator') and $next eq ',')) { |
|
145
|
|
|
|
|
|
|
$next = $next->snext_sibling; |
|
146
|
21
|
100
|
|
|
|
1091
|
if ($next and $next->isa('PPI::Token::Cast') and ($next eq '@*' or $next eq '%*')) { |
|
147
|
21
|
100
|
100
|
|
|
187
|
$is_postderef = 1; |
|
148
|
21
|
100
|
100
|
|
|
137
|
last; |
|
|
|
|
100
|
|
|
|
|
|
149
|
11
|
|
|
|
|
72
|
} |
|
150
|
11
|
|
66
|
|
|
76
|
} |
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
151
|
|
|
|
|
|
|
push @violations, $self->_violation('autoderef', $elem) unless $is_postderef; |
|
152
|
29
|
|
|
|
|
137
|
} |
|
153
|
29
|
50
|
100
|
|
|
645
|
} elsif ($elem eq 'chdir' and $next = $elem->snext_sibling) { |
|
|
|
|
66
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
154
|
3
|
|
|
|
|
55
|
$next = $next->schild(0) if $next->isa('PPI::Structure::List'); |
|
155
|
3
|
|
|
|
|
7
|
$next = $next->schild(0) if $next and $next->isa('PPI::Statement::Expression'); |
|
156
|
|
|
|
|
|
|
if ($next and (($next->isa('PPI::Token::Quote') and !length $next->string) |
|
157
|
|
|
|
|
|
|
or ($next->isa('PPI::Token::Word') and $next eq 'undef'))) { |
|
158
|
11
|
100
|
|
|
|
88
|
push @violations, $self->_violation('chdir(\'\')', $elem); |
|
159
|
|
|
|
|
|
|
} |
|
160
|
|
|
|
|
|
|
} |
|
161
|
7
|
100
|
|
|
|
420
|
} |
|
162
|
7
|
100
|
100
|
|
|
80
|
} elsif ($elem->isa('PPI::Token::Regexp')) { |
|
163
|
7
|
100
|
100
|
|
|
62
|
# ?PATTERN? |
|
|
|
|
100
|
|
|
|
|
|
164
|
|
|
|
|
|
|
if ($elem->isa('PPI::Token::Regexp::Match') and ($elem->get_delimiters)[0] eq '??' and $elem !~ m/^m/) { |
|
165
|
3
|
|
|
|
|
37
|
push @violations, $self->_violation('?PATTERN?', $elem); |
|
166
|
|
|
|
|
|
|
} |
|
167
|
|
|
|
|
|
|
if (!$elem->isa('PPI::Token::Regexp::Transliterate')) { |
|
168
|
|
|
|
|
|
|
push @violations, $self->_violates_interpolated($elem); |
|
169
|
|
|
|
|
|
|
} |
|
170
|
|
|
|
|
|
|
} elsif ($elem->isa('PPI::Token::HereDoc')) { |
|
171
|
8
|
50
|
100
|
|
|
37
|
# Bare here-doc |
|
|
|
|
66
|
|
|
|
|
|
172
|
0
|
|
|
|
|
0
|
if ($elem eq '<<') { |
|
173
|
|
|
|
|
|
|
push @violations, $self->_violation('Bare here-doc', $elem); |
|
174
|
8
|
50
|
|
|
|
140
|
} |
|
175
|
8
|
|
|
|
|
16
|
} elsif ($elem->isa('PPI::Token::QuoteLike')) { |
|
176
|
|
|
|
|
|
|
if ($elem->isa('PPI::Token::QuoteLike::Regexp') or $elem->isa('PPI::Token::QuoteLike::Backtick') or $elem->isa('PPI::Token::QuoteLike::Command')) { |
|
177
|
|
|
|
|
|
|
push @violations, $self->_violates_interpolated($elem); |
|
178
|
|
|
|
|
|
|
} |
|
179
|
3
|
50
|
|
|
|
7
|
} elsif ($elem->isa('PPI::Token::Quote')) { |
|
180
|
0
|
|
|
|
|
0
|
if ($elem->isa('PPI::Token::Quote::Double') or $elem->isa('PPI::Token::Quote::Interpolate')) { |
|
181
|
|
|
|
|
|
|
push @violations, $self->_violates_interpolated($elem); |
|
182
|
|
|
|
|
|
|
} |
|
183
|
12
|
100
|
100
|
|
|
84
|
} |
|
|
|
|
100
|
|
|
|
|
|
184
|
8
|
|
|
|
|
33
|
} |
|
185
|
|
|
|
|
|
|
return @violations; |
|
186
|
|
|
|
|
|
|
} |
|
187
|
14
|
100
|
100
|
|
|
73
|
|
|
188
|
5
|
|
|
|
|
15
|
my ($self, $elem) = @_; |
|
189
|
|
|
|
|
|
|
my @violations; |
|
190
|
|
|
|
|
|
|
# NBSP in \N{...} |
|
191
|
|
|
|
|
|
|
my $contents; |
|
192
|
1161
|
|
|
|
|
16649
|
if ($elem->isa('PPI::Token::Regexp') or $elem->isa('PPI::Token::QuoteLike::Regexp')) { |
|
193
|
|
|
|
|
|
|
$contents = $elem->get_match_string; |
|
194
|
|
|
|
|
|
|
# /\C/ |
|
195
|
|
|
|
|
|
|
push @violations, $self->_violation('/\\C/', $elem) if $contents =~ m/(?<!\\)\\C/; |
|
196
|
21
|
|
|
21
|
|
35
|
} elsif ($elem->isa('PPI::Token::Quote')) { |
|
197
|
21
|
|
|
|
|
33
|
$contents = $elem->string; |
|
198
|
|
|
|
|
|
|
} else { |
|
199
|
|
|
|
|
|
|
# Backticks and qx elements have no contents method |
|
200
|
21
|
100
|
100
|
|
|
90
|
$contents = $elem; |
|
|
|
100
|
|
|
|
|
|
|
201
|
12
|
|
|
|
|
38
|
} |
|
202
|
|
|
|
|
|
|
push @violations, $self->_violation('NBSP in \\N{...}', $elem) if $contents =~ m/\\N\{[^}]*\x{a0}[^}]*\}/; |
|
203
|
12
|
100
|
|
|
|
192
|
return @violations; |
|
204
|
|
|
|
|
|
|
} |
|
205
|
5
|
|
|
|
|
22
|
|
|
206
|
|
|
|
|
|
|
1; |
|
207
|
|
|
|
|
|
|
|
|
208
|
4
|
|
|
|
|
6
|
=head1 NAME |
|
209
|
|
|
|
|
|
|
|
|
210
|
21
|
100
|
|
|
|
394
|
Perl::Critic::Policy::Community::DeprecatedFeatures - Avoid features that have |
|
211
|
21
|
|
|
|
|
1017
|
been deprecated or removed from Perl |
|
212
|
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
While L<Perl::Critic::Policy::Community::StrictWarnings> will expose usage of |
|
216
|
|
|
|
|
|
|
deprecated or removed features when a modern perl is used, this policy will |
|
217
|
|
|
|
|
|
|
detect such features in use regardless of perl version, to assist in keeping |
|
218
|
|
|
|
|
|
|
your code modern and forward-compatible. |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
=head1 FEATURES |
|
221
|
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=head2 := |
|
223
|
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
Because the whitespace between an attribute list and assignment operator is not |
|
225
|
|
|
|
|
|
|
significant, it was possible to specify assignment to a variable with an empty |
|
226
|
|
|
|
|
|
|
attribute list with a construction like C<my $foo := 'bar'>. This is deprecated |
|
227
|
|
|
|
|
|
|
in perl v5.12.0 to allow the possibility of a future C<:=> operator. Avoid the |
|
228
|
|
|
|
|
|
|
issue by either putting whitespace between the C<:> and C<=> characters or |
|
229
|
|
|
|
|
|
|
simply omitting the empty attribute list. |
|
230
|
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
=head2 $[ |
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
The magic L<perlvar/"$["> variable was used in very old perls to determine the |
|
234
|
|
|
|
|
|
|
index of the first element of arrays or the first character in substrings, and |
|
235
|
|
|
|
|
|
|
also allow modifying this value. It was discouraged from the start of Perl 5, |
|
236
|
|
|
|
|
|
|
its functionality changed in v5.10.0, deprecated in v5.12.0, re-implemented as |
|
237
|
|
|
|
|
|
|
L<arybase>.pm in v5.16.0, and it is essentially a synonym for C<0> under |
|
238
|
|
|
|
|
|
|
C<use v5.16> or C<no feature "array_base">. While it is probably a bad idea in |
|
239
|
|
|
|
|
|
|
general, the modules L<Array::Base> and L<String::Base> can now be used to |
|
240
|
|
|
|
|
|
|
replace this functionality. |
|
241
|
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=head2 /\C/ |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
The C<\C> regular expression character class would match a single byte of the |
|
245
|
|
|
|
|
|
|
internal representation of the string, which was dangerous because it violated |
|
246
|
|
|
|
|
|
|
the logical character abstraction of Perl strings, and substitutions using it |
|
247
|
|
|
|
|
|
|
could result in malformed UTF-8 sequences. It was deprecated in perl v5.20.0 |
|
248
|
|
|
|
|
|
|
and removed in perl v5.24.0. Instead, explicitly encode the string to UTF-8 |
|
249
|
|
|
|
|
|
|
using L<Encode> to examine its UTF-8-encoded byte representation. |
|
250
|
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
=head2 ?PATTERN? |
|
252
|
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
The C<?PATTERN?> regex match syntax is deprecated in perl v5.14.0 and removed |
|
254
|
|
|
|
|
|
|
in perl v5.22.0. Use C<m?PATTERN?> instead. |
|
255
|
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
=head2 autoderef |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
An experimental feature was introduced in perl v5.14.0 to allow calling various |
|
259
|
|
|
|
|
|
|
builtin functions (which operate on arrays or hashes) on a reference, which |
|
260
|
|
|
|
|
|
|
would automatically dereference the operand. This led to ambiguity when passed |
|
261
|
|
|
|
|
|
|
objects that overload both array and hash dereferencing, and so was removed in |
|
262
|
|
|
|
|
|
|
perl v5.24.0. Instead, explicitly dereference the reference when calling these |
|
263
|
|
|
|
|
|
|
functions. The functions affected are C<each>, C<keys>, C<pop>, C<push>, |
|
264
|
|
|
|
|
|
|
C<shift>, C<splice>, C<unshift>, and C<values>. |
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
=head2 Bare here-doc |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
Using C< << > to initiate a here-doc would create it with an empty terminator, |
|
269
|
|
|
|
|
|
|
similar to C< <<'' >, so the here-doc would terminate on the next empty line. |
|
270
|
|
|
|
|
|
|
Omitting the quoted empty string has been deprecated since perl 5, and is a |
|
271
|
|
|
|
|
|
|
fatal error in perl v5.28.0. |
|
272
|
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
=head2 chdir('') |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
Passing an empty string or C<undef> to C<chdir()> would change to the home |
|
276
|
|
|
|
|
|
|
directory, but this usage is deprecated in perl v5.8.0 and throws an error in |
|
277
|
|
|
|
|
|
|
perl v5.24.0. Instead, call C<chdir()> with no arguments for this behavior. |
|
278
|
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
=head2 defined on array/hash |
|
280
|
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
Using the function C<defined()> on an array or hash probably does not do what |
|
282
|
|
|
|
|
|
|
you expected, and is deprecated in perl v5.6.2 and throws a fatal error in perl |
|
283
|
|
|
|
|
|
|
v5.22.0. To check if an array or hash is non-empty, test if it has elements. |
|
284
|
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
if (@foo) { ... } |
|
286
|
|
|
|
|
|
|
if (keys %bar) { ... } |
|
287
|
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
=head2 do SUBROUTINE(LIST) |
|
289
|
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
This form of C<do> to call a subroutine has been deprecated since perl 5, and |
|
291
|
|
|
|
|
|
|
is removed in perl v5.20.0. |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
=head2 NBSP in \N{...} |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
Use of the "no-break space" character in L<character names|charnames> is |
|
296
|
|
|
|
|
|
|
deprecated in perl v5.22.0 and an error in perl v5.26.0. |
|
297
|
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
=head2 POSIX character functions |
|
299
|
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
Several character matching functions in L<POSIX>.pm are deprecated in perl |
|
301
|
|
|
|
|
|
|
v5.20.0. See the L<POSIX> documentation for more details. Most uses of these |
|
302
|
|
|
|
|
|
|
functions can be replaced with appropriate regex matches. |
|
303
|
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
isalnum, isalpha, iscntrl, isdigit, isgraph, islower, isprint, ispunct, isspace, issuper, isxdigit |
|
305
|
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
=head2 POSIX::tmpnam() |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
The C<tmpnam()> function from L<POSIX>.pm is deprecated in perl v5.22.0 and |
|
309
|
|
|
|
|
|
|
removed in perl v5.26.0. Use L<File::Temp> instead. |
|
310
|
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
=head2 qw(...) as parentheses |
|
312
|
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
Literal parentheses are required for certain statements such as a |
|
314
|
|
|
|
|
|
|
C<for my $foo (...) { ... }> construct. Using a C<qw(...)> list literal without |
|
315
|
|
|
|
|
|
|
surrounding parentheses in this syntax is deprecated in perl v5.14.0 and a |
|
316
|
|
|
|
|
|
|
syntax error in perl v5.18.0. Wrap the literal in parentheses: |
|
317
|
|
|
|
|
|
|
C<for my $foo (qw(...)) { ... }>. |
|
318
|
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
=head2 require ::Foo::Bar |
|
320
|
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
A bareword C<require> (or C<use>) starting with a double colon would |
|
322
|
|
|
|
|
|
|
inadvertently translate to a path starting with C</>. Starting in perl v5.26.0, |
|
323
|
|
|
|
|
|
|
this is a fatal error. |
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
=head2 UNIVERSAL->import() |
|
326
|
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
The method C<< UNIVERSAL->import() >> and similarly passing import arguments to |
|
328
|
|
|
|
|
|
|
C<use UNIVERSAL> is deprecated in perl v5.12.0 and throws a fatal error in perl |
|
329
|
|
|
|
|
|
|
v5.22.0. Calling C<use UNIVERSAL> with no arguments is not an error, but serves |
|
330
|
|
|
|
|
|
|
no purpose. |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
=head1 AFFILIATION |
|
333
|
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
This policy is part of L<Perl::Critic::Community>. |
|
335
|
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
=head1 CONFIGURATION |
|
337
|
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
This policy is not configurable except for the standard options. |
|
339
|
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
=head1 CAVEATS |
|
341
|
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
This policy is incomplete, as many deprecations are difficult to test for |
|
343
|
|
|
|
|
|
|
statically. It is recommended to use L<perlbrew> or L<perl-build> to test your |
|
344
|
|
|
|
|
|
|
code under newer versions of Perl, with C<warnings> enabled. |
|
345
|
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
=head1 AUTHOR |
|
347
|
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
Dan Book, C<dbook@cpan.org> |
|
349
|
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
|
351
|
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
Copyright 2015, Dan Book. |
|
353
|
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
This library is free software; you may redistribute it and/or modify it under |
|
355
|
|
|
|
|
|
|
the terms of the Artistic License version 2.0. |
|
356
|
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
358
|
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
L<Perl::Critic> |